blob: ce91a4383343b14bdfbf264eb72a845c9ffd2988 [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$",
nyad2c548b2015-12-09 03:22:32200 r"^base[\\\/]process[\\\/]process_linux\.cc$",
thestig75844fdb2014-09-09 19:47:10201 r"^base[\\\/]process[\\\/]process_metrics_linux\.cc$",
tfarina0923ac52015-01-07 03:21:22202 r"^chrome[\\\/]browser[\\\/]chromeos[\\\/]boot_times_recorder\.cc$",
sky0e07a142016-03-25 21:27:31203 r"^chrome[\\\/]browser[\\\/]lifetime[\\\/]application_lifetime\.cc$",
alematee4016bb2014-11-12 17:38:51204 r"^chrome[\\\/]browser[\\\/]chromeos[\\\/]"
205 "customization_document_browsertest\.cc$",
philipj3f9d5bde2014-08-28 14:09:09206 r"^components[\\\/]crash[\\\/]app[\\\/]breakpad_mac\.mm$",
jochene9ba6dd2016-02-23 17:20:49207 r"^content[\\\/]shell[\\\/]browser[\\\/]layout_test[\\\/]" +
208 r"test_info_extractor\.cc$",
lukasza7947ccd2016-07-28 21:56:25209 r"^content[\\\/].*browser(|_)test[a-zA-Z_]*\.cc$",
[email protected]de7d61ff2013-08-20 11:30:41210 r"^content[\\\/]shell[\\\/]browser[\\\/]shell_browser_main\.cc$",
211 r"^content[\\\/]shell[\\\/]browser[\\\/]shell_message_filter\.cc$",
lukasza7947ccd2016-07-28 21:56:25212 r"^content[\\\/]test[\\\/]ppapi[\\\/]ppapi_test\.cc$",
jamesra03ae492014-10-03 04:26:48213 r"^mojo[\\\/]edk[\\\/]embedder[\\\/]" +
214 r"simple_platform_shared_buffer_posix\.cc$",
[email protected]398ad132013-04-02 15:11:01215 r"^net[\\\/]disk_cache[\\\/]cache_util\.cc$",
lukasza7947ccd2016-07-28 21:56:25216 r"^net[\\\/]cert[\\\/]test_root_certs\.cc$",
217 r"^net[\\\/]test[\\\/]embedded_test_server[\\\/]" +
218 r"embedded_test_server\.cc$",
219 r"^net[\\\/]test[\\\/]spawned_test_server[\\\/]local_test_server\.cc$",
220 r"^net[\\\/]test[\\\/]test_data_directory\.cc$",
[email protected]1f52a572014-05-12 23:21:54221 r"^net[\\\/]url_request[\\\/]test_url_fetcher_factory\.cc$",
sergeyu2c41f9842016-12-10 01:45:16222 r"^remoting[\\\/]protocol[\\\/]webrtc_transport\.cc$",
lambroslambrouf6fb94ea2016-06-27 21:21:53223 r"^ui[\\\/]base[\\\/]material_design[\\\/]"
224 "material_design_controller\.cc$",
kylechar16666242016-07-04 20:54:45225 r"^ui[\\\/]gl[\\\/]init[\\\/]gl_initializer_mac\.cc$",
226 r"^ui[\\\/]gl[\\\/]init[\\\/]gl_initializer_win\.cc$",
227 r"^ui[\\\/]gl[\\\/]init[\\\/]gl_initializer_x11\.cc$",
228 r"^ui[\\\/]ozone[\\\/]platform[\\\/]drm[\\\/]host[\\\/]"
229 "drm_display_host_manager\.cc$",
[email protected]7345da02012-11-27 14:31:49230 ),
[email protected]23e6cbc2012-06-16 18:51:20231 ),
[email protected]52657f62013-05-20 05:30:31232 (
tomhudsone2c14d552016-05-26 17:07:46233 'setMatrixClip',
234 (
235 'Overriding setMatrixClip() is prohibited; ',
236 'the base function is deprecated. ',
237 ),
238 True,
239 (),
240 ),
241 (
[email protected]52657f62013-05-20 05:30:31242 'SkRefPtr',
243 (
244 'The use of SkRefPtr is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22245 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31246 ),
247 True,
248 (),
249 ),
250 (
251 'SkAutoRef',
252 (
253 'The indirect use of SkRefPtr via SkAutoRef is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22254 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31255 ),
256 True,
257 (),
258 ),
259 (
260 'SkAutoTUnref',
261 (
262 'The use of SkAutoTUnref is dangerous because it implicitly ',
tomhudson7e6e0512016-04-19 19:27:22263 'converts to a raw pointer. Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31264 ),
265 True,
266 (),
267 ),
268 (
269 'SkAutoUnref',
270 (
271 'The indirect use of SkAutoTUnref through SkAutoUnref is dangerous ',
272 'because it implicitly converts to a raw pointer. ',
tomhudson7e6e0512016-04-19 19:27:22273 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31274 ),
275 True,
276 (),
277 ),
[email protected]d89eec82013-12-03 14:10:59278 (
279 r'/HANDLE_EINTR\(.*close',
280 (
281 'HANDLE_EINTR(close) is invalid. If close fails with EINTR, the file',
282 'descriptor will be closed, and it is incorrect to retry the close.',
283 'Either call close directly and ignore its return value, or wrap close',
284 'in IGNORE_EINTR to use its return value. See http://crbug.com/269623'
285 ),
286 True,
287 (),
288 ),
289 (
290 r'/IGNORE_EINTR\((?!.*close)',
291 (
292 'IGNORE_EINTR is only valid when wrapping close. To wrap other system',
293 'calls, use HANDLE_EINTR. See http://crbug.com/269623',
294 ),
295 True,
296 (
297 # Files that #define IGNORE_EINTR.
298 r'^base[\\\/]posix[\\\/]eintr_wrapper\.h$',
299 r'^ppapi[\\\/]tests[\\\/]test_broker\.cc$',
300 ),
301 ),
[email protected]ec5b3f02014-04-04 18:43:43302 (
303 r'/v8::Extension\(',
304 (
305 'Do not introduce new v8::Extensions into the code base, use',
306 'gin::Wrappable instead. See http://crbug.com/334679',
307 ),
308 True,
[email protected]f55c90ee62014-04-12 00:50:03309 (
joaodasilva718f87672014-08-30 09:25:49310 r'extensions[\\\/]renderer[\\\/]safe_builtins\.*',
[email protected]f55c90ee62014-04-12 00:50:03311 ),
[email protected]ec5b3f02014-04-04 18:43:43312 ),
skyostilf9469f72015-04-20 10:38:52313 (
jame2d1a952016-04-02 00:27:10314 '#pragma comment(lib,',
315 (
316 'Specify libraries to link with in build files and not in the source.',
317 ),
318 True,
319 (),
320 ),
[email protected]127f18ec2012-06-16 05:05:59321)
322
wnwenbdc444e2016-05-25 13:44:15323
mlamouria82272622014-09-16 18:45:04324_IPC_ENUM_TRAITS_DEPRECATED = (
325 'You are using IPC_ENUM_TRAITS() in your code. It has been deprecated.\n'
326 'See http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc')
327
[email protected]127f18ec2012-06-16 05:05:59328
[email protected]b00342e7f2013-03-26 16:21:54329_VALID_OS_MACROS = (
330 # Please keep sorted.
331 'OS_ANDROID',
332 'OS_BSD',
333 'OS_CAT', # For testing.
334 'OS_CHROMEOS',
335 'OS_FREEBSD',
336 'OS_IOS',
337 'OS_LINUX',
338 'OS_MACOSX',
339 'OS_NACL',
hidehikof7295f22014-10-28 11:57:21340 'OS_NACL_NONSFI',
341 'OS_NACL_SFI',
krytarowski969759f2016-07-31 23:55:12342 'OS_NETBSD',
[email protected]b00342e7f2013-03-26 16:21:54343 'OS_OPENBSD',
344 'OS_POSIX',
[email protected]eda7afa12014-02-06 12:27:37345 'OS_QNX',
[email protected]b00342e7f2013-03-26 16:21:54346 'OS_SOLARIS',
[email protected]b00342e7f2013-03-26 16:21:54347 'OS_WIN',
348)
349
350
agrievef32bcc72016-04-04 14:57:40351_ANDROID_SPECIFIC_PYDEPS_FILES = [
352 'build/android/test_runner.pydeps',
hzl9b15df52017-03-23 23:43:04353 'build/android/test_wrapper/logdog_wrapper.pydeps',
agrieve732db3a2016-04-26 19:18:19354 'net/tools/testserver/testserver.pydeps',
agrievef32bcc72016-04-04 14:57:40355]
356
wnwenbdc444e2016-05-25 13:44:15357
agrievef32bcc72016-04-04 14:57:40358_GENERIC_PYDEPS_FILES = [
agrievef32bcc72016-04-04 14:57:40359]
360
wnwenbdc444e2016-05-25 13:44:15361
agrievef32bcc72016-04-04 14:57:40362_ALL_PYDEPS_FILES = _ANDROID_SPECIFIC_PYDEPS_FILES + _GENERIC_PYDEPS_FILES
363
364
[email protected]55459852011-08-10 15:17:19365def _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api):
366 """Attempts to prevent use of functions intended only for testing in
367 non-testing code. For now this is just a best-effort implementation
368 that ignores header files and may have some false positives. A
369 better implementation would probably need a proper C++ parser.
370 """
371 # We only scan .cc files and the like, as the declaration of
372 # for-testing functions in header files are hard to distinguish from
373 # calls to such functions without a proper C++ parser.
[email protected]06e6d0ff2012-12-11 01:36:44374 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
[email protected]55459852011-08-10 15:17:19375
jochenc0d4808c2015-07-27 09:25:42376 base_function_pattern = r'[ :]test::[^\s]+|ForTest(s|ing)?|for_test(s|ing)?'
[email protected]55459852011-08-10 15:17:19377 inclusion_pattern = input_api.re.compile(r'(%s)\s*\(' % base_function_pattern)
[email protected]23501822014-05-14 02:06:09378 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_function_pattern)
[email protected]55459852011-08-10 15:17:19379 exclusion_pattern = input_api.re.compile(
380 r'::[A-Za-z0-9_]+(%s)|(%s)[^;]+\{' % (
381 base_function_pattern, base_function_pattern))
382
383 def FilterFile(affected_file):
[email protected]06e6d0ff2012-12-11 01:36:44384 black_list = (_EXCLUDED_PATHS +
385 _TEST_CODE_EXCLUDED_PATHS +
386 input_api.DEFAULT_BLACK_LIST)
[email protected]55459852011-08-10 15:17:19387 return input_api.FilterSourceFile(
388 affected_file,
389 white_list=(file_inclusion_pattern, ),
390 black_list=black_list)
391
392 problems = []
393 for f in input_api.AffectedSourceFiles(FilterFile):
394 local_path = f.LocalPath()
[email protected]825d27182014-01-02 21:24:24395 for line_number, line in f.ChangedContents():
[email protected]2fdd1f362013-01-16 03:56:03396 if (inclusion_pattern.search(line) and
[email protected]de4f7d22013-05-23 14:27:46397 not comment_pattern.search(line) and
[email protected]2fdd1f362013-01-16 03:56:03398 not exclusion_pattern.search(line)):
[email protected]55459852011-08-10 15:17:19399 problems.append(
[email protected]2fdd1f362013-01-16 03:56:03400 '%s:%d\n %s' % (local_path, line_number, line.strip()))
[email protected]55459852011-08-10 15:17:19401
402 if problems:
[email protected]f7051d52013-04-02 18:31:42403 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
[email protected]2fdd1f362013-01-16 03:56:03404 else:
405 return []
[email protected]55459852011-08-10 15:17:19406
407
[email protected]10689ca2011-09-02 02:31:54408def _CheckNoIOStreamInHeaders(input_api, output_api):
409 """Checks to make sure no .h files include <iostream>."""
410 files = []
411 pattern = input_api.re.compile(r'^#include\s*<iostream>',
412 input_api.re.MULTILINE)
413 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
414 if not f.LocalPath().endswith('.h'):
415 continue
416 contents = input_api.ReadFile(f)
417 if pattern.search(contents):
418 files.append(f)
419
420 if len(files):
yolandyandaabc6d2016-04-18 18:29:39421 return [output_api.PresubmitError(
[email protected]6c063c62012-07-11 19:11:06422 'Do not #include <iostream> in header files, since it inserts static '
423 'initialization into every file including the header. Instead, '
[email protected]10689ca2011-09-02 02:31:54424 '#include <ostream>. See http://crbug.com/94794',
425 files) ]
426 return []
427
428
[email protected]72df4e782012-06-21 16:28:18429def _CheckNoUNIT_TESTInSourceFiles(input_api, output_api):
danakj61c1aa22015-10-26 19:55:52430 """Checks to make sure no source files use UNIT_TEST."""
[email protected]72df4e782012-06-21 16:28:18431 problems = []
432 for f in input_api.AffectedFiles():
433 if (not f.LocalPath().endswith(('.cc', '.mm'))):
434 continue
435
436 for line_num, line in f.ChangedContents():
[email protected]549f86a2013-11-19 13:00:04437 if 'UNIT_TEST ' in line or line.endswith('UNIT_TEST'):
[email protected]72df4e782012-06-21 16:28:18438 problems.append(' %s:%d' % (f.LocalPath(), line_num))
439
440 if not problems:
441 return []
442 return [output_api.PresubmitPromptWarning('UNIT_TEST is only for headers.\n' +
443 '\n'.join(problems))]
444
445
danakj61c1aa22015-10-26 19:55:52446def _CheckDCHECK_IS_ONHasBraces(input_api, output_api):
kjellanderaee306632017-02-22 19:26:57447 """Checks to make sure DCHECK_IS_ON() does not skip the parentheses."""
danakj61c1aa22015-10-26 19:55:52448 errors = []
449 pattern = input_api.re.compile(r'DCHECK_IS_ON(?!\(\))',
450 input_api.re.MULTILINE)
451 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
452 if (not f.LocalPath().endswith(('.cc', '.mm', '.h'))):
453 continue
454 for lnum, line in f.ChangedContents():
455 if input_api.re.search(pattern, line):
dchenge07de812016-06-20 19:27:17456 errors.append(output_api.PresubmitError(
457 ('%s:%d: Use of DCHECK_IS_ON() must be written as "#if ' +
kjellanderaee306632017-02-22 19:26:57458 'DCHECK_IS_ON()", not forgetting the parentheses.')
dchenge07de812016-06-20 19:27:17459 % (f.LocalPath(), lnum)))
danakj61c1aa22015-10-26 19:55:52460 return errors
461
462
mcasasb7440c282015-02-04 14:52:19463def _FindHistogramNameInLine(histogram_name, line):
464 """Tries to find a histogram name or prefix in a line."""
465 if not "affected-histogram" in line:
466 return histogram_name in line
467 # A histogram_suffixes tag type has an affected-histogram name as a prefix of
468 # the histogram_name.
469 if not '"' in line:
470 return False
471 histogram_prefix = line.split('\"')[1]
472 return histogram_prefix in histogram_name
473
474
475def _CheckUmaHistogramChanges(input_api, output_api):
476 """Check that UMA histogram names in touched lines can still be found in other
477 lines of the patch or in histograms.xml. Note that this check would not catch
478 the reverse: changes in histograms.xml not matched in the code itself."""
479 touched_histograms = []
480 histograms_xml_modifications = []
481 pattern = input_api.re.compile('UMA_HISTOGRAM.*\("(.*)"')
482 for f in input_api.AffectedFiles():
483 # If histograms.xml itself is modified, keep the modified lines for later.
484 if f.LocalPath().endswith(('histograms.xml')):
485 histograms_xml_modifications = f.ChangedContents()
486 continue
487 if not f.LocalPath().endswith(('cc', 'mm', 'cpp')):
488 continue
489 for line_num, line in f.ChangedContents():
490 found = pattern.search(line)
491 if found:
492 touched_histograms.append([found.group(1), f, line_num])
493
494 # Search for the touched histogram names in the local modifications to
495 # histograms.xml, and, if not found, on the base histograms.xml file.
496 unmatched_histograms = []
497 for histogram_info in touched_histograms:
498 histogram_name_found = False
499 for line_num, line in histograms_xml_modifications:
500 histogram_name_found = _FindHistogramNameInLine(histogram_info[0], line)
501 if histogram_name_found:
502 break
503 if not histogram_name_found:
504 unmatched_histograms.append(histogram_info)
505
eromanb90c82e7e32015-04-01 15:13:49506 histograms_xml_path = 'tools/metrics/histograms/histograms.xml'
mcasasb7440c282015-02-04 14:52:19507 problems = []
508 if unmatched_histograms:
eromanb90c82e7e32015-04-01 15:13:49509 with open(histograms_xml_path) as histograms_xml:
mcasasb7440c282015-02-04 14:52:19510 for histogram_name, f, line_num in unmatched_histograms:
mcasas39c1b8b2015-02-25 15:33:45511 histograms_xml.seek(0)
mcasasb7440c282015-02-04 14:52:19512 histogram_name_found = False
513 for line in histograms_xml:
514 histogram_name_found = _FindHistogramNameInLine(histogram_name, line)
515 if histogram_name_found:
516 break
517 if not histogram_name_found:
518 problems.append(' [%s:%d] %s' %
519 (f.LocalPath(), line_num, histogram_name))
520
521 if not problems:
522 return []
523 return [output_api.PresubmitPromptWarning('Some UMA_HISTOGRAM lines have '
524 'been modified and the associated histogram name has no match in either '
eromanb90c82e7e32015-04-01 15:13:49525 '%s or the modifications of it:' % (histograms_xml_path), problems)]
mcasasb7440c282015-02-04 14:52:19526
wnwenbdc444e2016-05-25 13:44:15527
yolandyandaabc6d2016-04-18 18:29:39528def _CheckFlakyTestUsage(input_api, output_api):
529 """Check that FlakyTest annotation is our own instead of the android one"""
530 pattern = input_api.re.compile(r'import android.test.FlakyTest;')
531 files = []
532 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
533 if f.LocalPath().endswith('Test.java'):
534 if pattern.search(input_api.ReadFile(f)):
535 files.append(f)
536 if len(files):
537 return [output_api.PresubmitError(
538 'Use org.chromium.base.test.util.FlakyTest instead of '
539 'android.test.FlakyTest',
540 files)]
541 return []
mcasasb7440c282015-02-04 14:52:19542
wnwenbdc444e2016-05-25 13:44:15543
[email protected]8ea5d4b2011-09-13 21:49:22544def _CheckNoNewWStrings(input_api, output_api):
545 """Checks to make sure we don't introduce use of wstrings."""
[email protected]55463aa62011-10-12 00:48:27546 problems = []
[email protected]8ea5d4b2011-09-13 21:49:22547 for f in input_api.AffectedFiles():
[email protected]b5c24292011-11-28 14:38:20548 if (not f.LocalPath().endswith(('.cc', '.h')) or
scottmge6f04402014-11-05 01:59:57549 f.LocalPath().endswith(('test.cc', '_win.cc', '_win.h')) or
pennymac84fd6692016-07-13 22:35:34550 '/win/' in f.LocalPath() or
551 'chrome_elf' in f.LocalPath() or
552 'install_static' in f.LocalPath()):
[email protected]b5c24292011-11-28 14:38:20553 continue
[email protected]8ea5d4b2011-09-13 21:49:22554
[email protected]a11dbe9b2012-08-07 01:32:58555 allowWString = False
[email protected]b5c24292011-11-28 14:38:20556 for line_num, line in f.ChangedContents():
[email protected]a11dbe9b2012-08-07 01:32:58557 if 'presubmit: allow wstring' in line:
558 allowWString = True
559 elif not allowWString and 'wstring' in line:
[email protected]55463aa62011-10-12 00:48:27560 problems.append(' %s:%d' % (f.LocalPath(), line_num))
[email protected]a11dbe9b2012-08-07 01:32:58561 allowWString = False
562 else:
563 allowWString = False
[email protected]8ea5d4b2011-09-13 21:49:22564
[email protected]55463aa62011-10-12 00:48:27565 if not problems:
566 return []
567 return [output_api.PresubmitPromptWarning('New code should not use wstrings.'
[email protected]a11dbe9b2012-08-07 01:32:58568 ' If you are calling a cross-platform API that accepts a wstring, '
569 'fix the API.\n' +
[email protected]55463aa62011-10-12 00:48:27570 '\n'.join(problems))]
[email protected]8ea5d4b2011-09-13 21:49:22571
572
[email protected]2a8ac9c2011-10-19 17:20:44573def _CheckNoDEPSGIT(input_api, output_api):
574 """Make sure .DEPS.git is never modified manually."""
575 if any(f.LocalPath().endswith('.DEPS.git') for f in
576 input_api.AffectedFiles()):
577 return [output_api.PresubmitError(
578 'Never commit changes to .DEPS.git. This file is maintained by an\n'
579 'automated system based on what\'s in DEPS and your changes will be\n'
580 'overwritten.\n'
[email protected]cb706912014-06-28 20:46:34581 '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:44582 'for more information')]
583 return []
584
585
tandriief664692014-09-23 14:51:47586def _CheckValidHostsInDEPS(input_api, output_api):
587 """Checks that DEPS file deps are from allowed_hosts."""
588 # Run only if DEPS file has been modified to annoy fewer bystanders.
589 if all(f.LocalPath() != 'DEPS' for f in input_api.AffectedFiles()):
590 return []
591 # Outsource work to gclient verify
592 try:
593 input_api.subprocess.check_output(['gclient', 'verify'])
594 return []
595 except input_api.subprocess.CalledProcessError, error:
596 return [output_api.PresubmitError(
597 'DEPS file must have only git dependencies.',
598 long_text=error.output)]
599
600
[email protected]127f18ec2012-06-16 05:05:59601def _CheckNoBannedFunctions(input_api, output_api):
602 """Make sure that banned functions are not used."""
603 warnings = []
604 errors = []
605
wnwenbdc444e2016-05-25 13:44:15606 def IsBlacklisted(affected_file, blacklist):
607 local_path = affected_file.LocalPath()
608 for item in blacklist:
609 if input_api.re.match(item, local_path):
610 return True
611 return False
612
613 def CheckForMatch(affected_file, line_num, line, func_name, message, error):
614 matched = False
615 if func_name[0:1] == '/':
616 regex = func_name[1:]
617 if input_api.re.search(regex, line):
618 matched = True
619 elif func_name in line:
dchenge07de812016-06-20 19:27:17620 matched = True
wnwenbdc444e2016-05-25 13:44:15621 if matched:
dchenge07de812016-06-20 19:27:17622 problems = warnings
wnwenbdc444e2016-05-25 13:44:15623 if error:
dchenge07de812016-06-20 19:27:17624 problems = errors
wnwenbdc444e2016-05-25 13:44:15625 problems.append(' %s:%d:' % (affected_file.LocalPath(), line_num))
626 for message_line in message:
627 problems.append(' %s' % message_line)
628
[email protected]127f18ec2012-06-16 05:05:59629 file_filter = lambda f: f.LocalPath().endswith(('.mm', '.m', '.h'))
630 for f in input_api.AffectedFiles(file_filter=file_filter):
631 for line_num, line in f.ChangedContents():
632 for func_name, message, error in _BANNED_OBJC_FUNCTIONS:
wnwenbdc444e2016-05-25 13:44:15633 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:59634
635 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
636 for f in input_api.AffectedFiles(file_filter=file_filter):
637 for line_num, line in f.ChangedContents():
[email protected]7345da02012-11-27 14:31:49638 for func_name, message, error, excluded_paths in _BANNED_CPP_FUNCTIONS:
[email protected]7345da02012-11-27 14:31:49639 if IsBlacklisted(f, excluded_paths):
640 continue
wnwenbdc444e2016-05-25 13:44:15641 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:59642
643 result = []
644 if (warnings):
645 result.append(output_api.PresubmitPromptWarning(
646 'Banned functions were used.\n' + '\n'.join(warnings)))
647 if (errors):
648 result.append(output_api.PresubmitError(
649 'Banned functions were used.\n' + '\n'.join(errors)))
650 return result
651
652
[email protected]6c063c62012-07-11 19:11:06653def _CheckNoPragmaOnce(input_api, output_api):
654 """Make sure that banned functions are not used."""
655 files = []
656 pattern = input_api.re.compile(r'^#pragma\s+once',
657 input_api.re.MULTILINE)
658 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
659 if not f.LocalPath().endswith('.h'):
660 continue
661 contents = input_api.ReadFile(f)
662 if pattern.search(contents):
663 files.append(f)
664
665 if files:
666 return [output_api.PresubmitError(
667 'Do not use #pragma once in header files.\n'
668 'See http://www.chromium.org/developers/coding-style#TOC-File-headers',
669 files)]
670 return []
671
[email protected]127f18ec2012-06-16 05:05:59672
[email protected]e7479052012-09-19 00:26:12673def _CheckNoTrinaryTrueFalse(input_api, output_api):
674 """Checks to make sure we don't introduce use of foo ? true : false."""
675 problems = []
676 pattern = input_api.re.compile(r'\?\s*(true|false)\s*:\s*(true|false)')
677 for f in input_api.AffectedFiles():
678 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
679 continue
680
681 for line_num, line in f.ChangedContents():
682 if pattern.match(line):
683 problems.append(' %s:%d' % (f.LocalPath(), line_num))
684
685 if not problems:
686 return []
687 return [output_api.PresubmitPromptWarning(
688 'Please consider avoiding the "? true : false" pattern if possible.\n' +
689 '\n'.join(problems))]
690
691
[email protected]55f9f382012-07-31 11:02:18692def _CheckUnwantedDependencies(input_api, output_api):
rhalavati08acd232017-04-03 07:23:28693 """Runs checkdeps on #include and import statements added in this
[email protected]55f9f382012-07-31 11:02:18694 change. Breaking - rules is an error, breaking ! rules is a
695 warning.
696 """
mohan.reddyf21db962014-10-16 12:26:47697 import sys
[email protected]55f9f382012-07-31 11:02:18698 # We need to wait until we have an input_api object and use this
699 # roundabout construct to import checkdeps because this file is
700 # eval-ed and thus doesn't have __file__.
701 original_sys_path = sys.path
702 try:
703 sys.path = sys.path + [input_api.os_path.join(
[email protected]5298cc982014-05-29 20:53:47704 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
[email protected]55f9f382012-07-31 11:02:18705 import checkdeps
706 from cpp_checker import CppChecker
rhalavati08acd232017-04-03 07:23:28707 from proto_checker import ProtoChecker
[email protected]55f9f382012-07-31 11:02:18708 from rules import Rule
709 finally:
710 # Restore sys.path to what it was before.
711 sys.path = original_sys_path
712
713 added_includes = []
rhalavati08acd232017-04-03 07:23:28714 added_imports = []
[email protected]55f9f382012-07-31 11:02:18715 for f in input_api.AffectedFiles():
rhalavati08acd232017-04-03 07:23:28716 if CppChecker.IsCppFile(f.LocalPath()):
717 changed_lines = [line for line_num, line in f.ChangedContents()]
718 added_includes.append([f.LocalPath(), changed_lines])
719 elif ProtoChecker.IsProtoFile(f.LocalPath()):
720 changed_lines = [line for line_num, line in f.ChangedContents()]
721 added_imports.append([f.LocalPath(), changed_lines])
[email protected]55f9f382012-07-31 11:02:18722
[email protected]26385172013-05-09 23:11:35723 deps_checker = checkdeps.DepsChecker(input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:18724
725 error_descriptions = []
726 warning_descriptions = []
rhalavati08acd232017-04-03 07:23:28727 error_subjects = set()
728 warning_subjects = set()
[email protected]55f9f382012-07-31 11:02:18729 for path, rule_type, rule_description in deps_checker.CheckAddedCppIncludes(
730 added_includes):
731 description_with_path = '%s\n %s' % (path, rule_description)
732 if rule_type == Rule.DISALLOW:
733 error_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:28734 error_subjects.add("#includes")
[email protected]55f9f382012-07-31 11:02:18735 else:
736 warning_descriptions.append(description_with_path)
rhalavati08acd232017-04-03 07:23:28737 warning_subjects.add("#includes")
738
739 for path, rule_type, rule_description in deps_checker.CheckAddedProtoImports(
740 added_imports):
741 description_with_path = '%s\n %s' % (path, rule_description)
742 if rule_type == Rule.DISALLOW:
743 error_descriptions.append(description_with_path)
744 error_subjects.add("imports")
745 else:
746 warning_descriptions.append(description_with_path)
747 warning_subjects.add("imports")
[email protected]55f9f382012-07-31 11:02:18748
749 results = []
750 if error_descriptions:
751 results.append(output_api.PresubmitError(
rhalavati08acd232017-04-03 07:23:28752 'You added one or more %s that violate checkdeps rules.'
753 % " and ".join(error_subjects),
[email protected]55f9f382012-07-31 11:02:18754 error_descriptions))
755 if warning_descriptions:
[email protected]f7051d52013-04-02 18:31:42756 results.append(output_api.PresubmitPromptOrNotify(
rhalavati08acd232017-04-03 07:23:28757 'You added one or more %s of files that are temporarily\n'
[email protected]55f9f382012-07-31 11:02:18758 'allowed but being removed. Can you avoid introducing the\n'
rhalavati08acd232017-04-03 07:23:28759 '%s? See relevant DEPS file(s) for details and contacts.' %
760 (" and ".join(warning_subjects), "/".join(warning_subjects)),
[email protected]55f9f382012-07-31 11:02:18761 warning_descriptions))
762 return results
763
764
[email protected]fbcafe5a2012-08-08 15:31:22765def _CheckFilePermissions(input_api, output_api):
766 """Check that all files have their permissions properly set."""
[email protected]791507202014-02-03 23:19:15767 if input_api.platform == 'win32':
768 return []
raphael.kubo.da.costac1d13e60b2016-04-01 11:49:29769 checkperms_tool = input_api.os_path.join(
770 input_api.PresubmitLocalPath(),
771 'tools', 'checkperms', 'checkperms.py')
772 args = [input_api.python_executable, checkperms_tool,
mohan.reddyf21db962014-10-16 12:26:47773 '--root', input_api.change.RepositoryRoot()]
[email protected]fbcafe5a2012-08-08 15:31:22774 for f in input_api.AffectedFiles():
775 args += ['--file', f.LocalPath()]
phajdan.jr5ea54792015-10-14 10:51:11776 try:
777 input_api.subprocess.check_output(args)
778 return []
779 except input_api.subprocess.CalledProcessError as error:
780 return [output_api.PresubmitError(
781 'checkperms.py failed:',
782 long_text=error.output)]
[email protected]fbcafe5a2012-08-08 15:31:22783
784
robertocn832f5992017-01-04 19:01:30785def _CheckTeamTags(input_api, output_api):
786 """Checks that OWNERS files have consistent TEAM and COMPONENT tags."""
787 checkteamtags_tool = input_api.os_path.join(
788 input_api.PresubmitLocalPath(),
789 'tools', 'checkteamtags', 'checkteamtags.py')
790 args = [input_api.python_executable, checkteamtags_tool,
791 '--root', input_api.change.RepositoryRoot()]
robertocn5eb82312017-01-09 20:27:22792 files = [f.LocalPath() for f in input_api.AffectedFiles(include_deletes=False)
robertocn832f5992017-01-04 19:01:30793 if input_api.os_path.basename(f.AbsoluteLocalPath()).upper() ==
794 'OWNERS']
795 try:
796 if files:
797 input_api.subprocess.check_output(args + files)
798 return []
799 except input_api.subprocess.CalledProcessError as error:
800 return [output_api.PresubmitError(
801 'checkteamtags.py failed:',
802 long_text=error.output)]
803
804
[email protected]c8278b32012-10-30 20:35:49805def _CheckNoAuraWindowPropertyHInHeaders(input_api, output_api):
806 """Makes sure we don't include ui/aura/window_property.h
807 in header files.
808 """
809 pattern = input_api.re.compile(r'^#include\s*"ui/aura/window_property.h"')
810 errors = []
811 for f in input_api.AffectedFiles():
812 if not f.LocalPath().endswith('.h'):
813 continue
814 for line_num, line in f.ChangedContents():
815 if pattern.match(line):
816 errors.append(' %s:%d' % (f.LocalPath(), line_num))
817
818 results = []
819 if errors:
820 results.append(output_api.PresubmitError(
821 'Header files should not include ui/aura/window_property.h', errors))
822 return results
823
824
[email protected]cf9b78f2012-11-14 11:40:28825def _CheckIncludeOrderForScope(scope, input_api, file_path, changed_linenums):
826 """Checks that the lines in scope occur in the right order.
827
828 1. C system files in alphabetical order
829 2. C++ system files in alphabetical order
830 3. Project's .h files
831 """
832
833 c_system_include_pattern = input_api.re.compile(r'\s*#include <.*\.h>')
834 cpp_system_include_pattern = input_api.re.compile(r'\s*#include <.*>')
835 custom_include_pattern = input_api.re.compile(r'\s*#include ".*')
836
837 C_SYSTEM_INCLUDES, CPP_SYSTEM_INCLUDES, CUSTOM_INCLUDES = range(3)
838
839 state = C_SYSTEM_INCLUDES
840
841 previous_line = ''
[email protected]728b9bb2012-11-14 20:38:57842 previous_line_num = 0
[email protected]cf9b78f2012-11-14 11:40:28843 problem_linenums = []
brucedawson70fadb02015-06-30 17:47:55844 out_of_order = " - line belongs before previous line"
[email protected]cf9b78f2012-11-14 11:40:28845 for line_num, line in scope:
846 if c_system_include_pattern.match(line):
847 if state != C_SYSTEM_INCLUDES:
brucedawson70fadb02015-06-30 17:47:55848 problem_linenums.append((line_num, previous_line_num,
849 " - C system include file in wrong block"))
[email protected]cf9b78f2012-11-14 11:40:28850 elif previous_line and previous_line > line:
brucedawson70fadb02015-06-30 17:47:55851 problem_linenums.append((line_num, previous_line_num,
852 out_of_order))
[email protected]cf9b78f2012-11-14 11:40:28853 elif cpp_system_include_pattern.match(line):
854 if state == C_SYSTEM_INCLUDES:
855 state = CPP_SYSTEM_INCLUDES
856 elif state == CUSTOM_INCLUDES:
brucedawson70fadb02015-06-30 17:47:55857 problem_linenums.append((line_num, previous_line_num,
858 " - c++ system include file in wrong block"))
[email protected]cf9b78f2012-11-14 11:40:28859 elif previous_line and previous_line > line:
brucedawson70fadb02015-06-30 17:47:55860 problem_linenums.append((line_num, previous_line_num, out_of_order))
[email protected]cf9b78f2012-11-14 11:40:28861 elif custom_include_pattern.match(line):
862 if state != CUSTOM_INCLUDES:
863 state = CUSTOM_INCLUDES
864 elif previous_line and previous_line > line:
brucedawson70fadb02015-06-30 17:47:55865 problem_linenums.append((line_num, previous_line_num, out_of_order))
[email protected]cf9b78f2012-11-14 11:40:28866 else:
brucedawson70fadb02015-06-30 17:47:55867 problem_linenums.append((line_num, previous_line_num,
868 "Unknown include type"))
[email protected]cf9b78f2012-11-14 11:40:28869 previous_line = line
[email protected]728b9bb2012-11-14 20:38:57870 previous_line_num = line_num
[email protected]cf9b78f2012-11-14 11:40:28871
872 warnings = []
brucedawson70fadb02015-06-30 17:47:55873 for (line_num, previous_line_num, failure_type) in problem_linenums:
[email protected]728b9bb2012-11-14 20:38:57874 if line_num in changed_linenums or previous_line_num in changed_linenums:
brucedawson70fadb02015-06-30 17:47:55875 warnings.append(' %s:%d:%s' % (file_path, line_num, failure_type))
[email protected]cf9b78f2012-11-14 11:40:28876 return warnings
877
878
[email protected]ac294a12012-12-06 16:38:43879def _CheckIncludeOrderInFile(input_api, f, changed_linenums):
[email protected]cf9b78f2012-11-14 11:40:28880 """Checks the #include order for the given file f."""
881
[email protected]2299dcf2012-11-15 19:56:24882 system_include_pattern = input_api.re.compile(r'\s*#include \<.*')
[email protected]23093b62013-09-20 12:16:30883 # Exclude the following includes from the check:
884 # 1) #include <.../...>, e.g., <sys/...> includes often need to appear in a
885 # specific order.
886 # 2) <atlbase.h>, "build/build_config.h"
887 excluded_include_pattern = input_api.re.compile(
888 r'\s*#include (\<.*/.*|\<atlbase\.h\>|"build/build_config.h")')
[email protected]2299dcf2012-11-15 19:56:24889 custom_include_pattern = input_api.re.compile(r'\s*#include "(?P<FILE>.*)"')
[email protected]3e83618c2013-10-09 22:32:33890 # Match the final or penultimate token if it is xxxtest so we can ignore it
891 # when considering the special first include.
892 test_file_tag_pattern = input_api.re.compile(
893 r'_[a-z]+test(?=(_[a-zA-Z0-9]+)?\.)')
[email protected]0e5c1852012-12-18 20:17:11894 if_pattern = input_api.re.compile(
895 r'\s*#\s*(if|elif|else|endif|define|undef).*')
896 # Some files need specialized order of includes; exclude such files from this
897 # check.
898 uncheckable_includes_pattern = input_api.re.compile(
899 r'\s*#include '
900 '("ipc/.*macros\.h"|<windows\.h>|".*gl.*autogen.h")\s*')
[email protected]cf9b78f2012-11-14 11:40:28901
902 contents = f.NewContents()
903 warnings = []
904 line_num = 0
905
[email protected]ac294a12012-12-06 16:38:43906 # Handle the special first include. If the first include file is
907 # some/path/file.h, the corresponding including file can be some/path/file.cc,
908 # some/other/path/file.cc, some/path/file_platform.cc, some/path/file-suffix.h
909 # etc. It's also possible that no special first include exists.
[email protected]3e83618c2013-10-09 22:32:33910 # If the included file is some/path/file_platform.h the including file could
911 # also be some/path/file_xxxtest_platform.h.
912 including_file_base_name = test_file_tag_pattern.sub(
913 '', input_api.os_path.basename(f.LocalPath()))
914
[email protected]ac294a12012-12-06 16:38:43915 for line in contents:
916 line_num += 1
917 if system_include_pattern.match(line):
918 # No special first include -> process the line again along with normal
919 # includes.
920 line_num -= 1
921 break
922 match = custom_include_pattern.match(line)
923 if match:
924 match_dict = match.groupdict()
[email protected]3e83618c2013-10-09 22:32:33925 header_basename = test_file_tag_pattern.sub(
926 '', input_api.os_path.basename(match_dict['FILE'])).replace('.h', '')
927
928 if header_basename not in including_file_base_name:
[email protected]2299dcf2012-11-15 19:56:24929 # No special first include -> process the line again along with normal
930 # includes.
931 line_num -= 1
[email protected]ac294a12012-12-06 16:38:43932 break
[email protected]cf9b78f2012-11-14 11:40:28933
934 # Split into scopes: Each region between #if and #endif is its own scope.
935 scopes = []
936 current_scope = []
937 for line in contents[line_num:]:
938 line_num += 1
[email protected]0e5c1852012-12-18 20:17:11939 if uncheckable_includes_pattern.match(line):
[email protected]4436c9e2014-01-07 23:19:54940 continue
[email protected]2309b0fa02012-11-16 12:18:27941 if if_pattern.match(line):
[email protected]cf9b78f2012-11-14 11:40:28942 scopes.append(current_scope)
943 current_scope = []
[email protected]962f117e2012-11-22 18:11:56944 elif ((system_include_pattern.match(line) or
945 custom_include_pattern.match(line)) and
946 not excluded_include_pattern.match(line)):
[email protected]cf9b78f2012-11-14 11:40:28947 current_scope.append((line_num, line))
948 scopes.append(current_scope)
949
950 for scope in scopes:
951 warnings.extend(_CheckIncludeOrderForScope(scope, input_api, f.LocalPath(),
952 changed_linenums))
953 return warnings
954
955
956def _CheckIncludeOrder(input_api, output_api):
957 """Checks that the #include order is correct.
958
959 1. The corresponding header for source files.
960 2. C system files in alphabetical order
961 3. C++ system files in alphabetical order
962 4. Project's .h files in alphabetical order
963
[email protected]ac294a12012-12-06 16:38:43964 Each region separated by #if, #elif, #else, #endif, #define and #undef follows
965 these rules separately.
[email protected]cf9b78f2012-11-14 11:40:28966 """
[email protected]e120b012014-08-15 19:08:35967 def FileFilterIncludeOrder(affected_file):
968 black_list = (_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
969 return input_api.FilterSourceFile(affected_file, black_list=black_list)
[email protected]cf9b78f2012-11-14 11:40:28970
971 warnings = []
[email protected]e120b012014-08-15 19:08:35972 for f in input_api.AffectedFiles(file_filter=FileFilterIncludeOrder):
tapted574f09c2015-05-19 13:08:08973 if f.LocalPath().endswith(('.cc', '.h', '.mm')):
[email protected]ac294a12012-12-06 16:38:43974 changed_linenums = set(line_num for line_num, _ in f.ChangedContents())
975 warnings.extend(_CheckIncludeOrderInFile(input_api, f, changed_linenums))
[email protected]cf9b78f2012-11-14 11:40:28976
977 results = []
978 if warnings:
[email protected]f7051d52013-04-02 18:31:42979 results.append(output_api.PresubmitPromptOrNotify(_INCLUDE_ORDER_WARNING,
[email protected]120cf540d2012-12-10 17:55:53980 warnings))
[email protected]cf9b78f2012-11-14 11:40:28981 return results
982
983
[email protected]70ca77752012-11-20 03:45:03984def _CheckForVersionControlConflictsInFile(input_api, f):
985 pattern = input_api.re.compile('^(?:<<<<<<<|>>>>>>>) |^=======$')
986 errors = []
987 for line_num, line in f.ChangedContents():
dbeam95c35a2f2015-06-02 01:40:23988 if f.LocalPath().endswith('.md'):
989 # First-level headers in markdown look a lot like version control
990 # conflict markers. http://daringfireball.net/projects/markdown/basics
991 continue
[email protected]70ca77752012-11-20 03:45:03992 if pattern.match(line):
993 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
994 return errors
995
996
997def _CheckForVersionControlConflicts(input_api, output_api):
998 """Usually this is not intentional and will cause a compile failure."""
999 errors = []
1000 for f in input_api.AffectedFiles():
1001 errors.extend(_CheckForVersionControlConflictsInFile(input_api, f))
1002
1003 results = []
1004 if errors:
1005 results.append(output_api.PresubmitError(
1006 'Version control conflict markers found, please resolve.', errors))
1007 return results
1008
estadee17314a02017-01-12 16:22:161009def _CheckGoogleSupportAnswerUrl(input_api, output_api):
1010 pattern = input_api.re.compile('support\.google\.com\/chrome.*/answer')
1011 errors = []
1012 for f in input_api.AffectedFiles():
1013 for line_num, line in f.ChangedContents():
1014 if pattern.search(line):
1015 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
1016
1017 results = []
1018 if errors:
1019 results.append(output_api.PresubmitPromptWarning(
1020 'Found Google support URL addressed by answer number. Please replace with '
1021 'a p= identifier instead. See crbug.com/679462\n', errors))
1022 return results
1023
[email protected]70ca77752012-11-20 03:45:031024
[email protected]06e6d0ff2012-12-11 01:36:441025def _CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api):
1026 def FilterFile(affected_file):
1027 """Filter function for use with input_api.AffectedSourceFiles,
1028 below. This filters out everything except non-test files from
1029 top-level directories that generally speaking should not hard-code
1030 service URLs (e.g. src/android_webview/, src/content/ and others).
1031 """
1032 return input_api.FilterSourceFile(
1033 affected_file,
[email protected]78bb39d62012-12-11 15:11:561034 white_list=(r'^(android_webview|base|content|net)[\\\/].*', ),
[email protected]06e6d0ff2012-12-11 01:36:441035 black_list=(_EXCLUDED_PATHS +
1036 _TEST_CODE_EXCLUDED_PATHS +
1037 input_api.DEFAULT_BLACK_LIST))
1038
reillyi38965732015-11-16 18:27:331039 base_pattern = ('"[^"]*(google|googleapis|googlezip|googledrive|appspot)'
1040 '\.(com|net)[^"]*"')
[email protected]de4f7d22013-05-23 14:27:461041 comment_pattern = input_api.re.compile('//.*%s' % base_pattern)
1042 pattern = input_api.re.compile(base_pattern)
[email protected]06e6d0ff2012-12-11 01:36:441043 problems = [] # items are (filename, line_number, line)
1044 for f in input_api.AffectedSourceFiles(FilterFile):
1045 for line_num, line in f.ChangedContents():
[email protected]de4f7d22013-05-23 14:27:461046 if not comment_pattern.search(line) and pattern.search(line):
[email protected]06e6d0ff2012-12-11 01:36:441047 problems.append((f.LocalPath(), line_num, line))
1048
1049 if problems:
[email protected]f7051d52013-04-02 18:31:421050 return [output_api.PresubmitPromptOrNotify(
[email protected]06e6d0ff2012-12-11 01:36:441051 'Most layers below src/chrome/ should not hardcode service URLs.\n'
[email protected]b0149772014-03-27 16:47:581052 'Are you sure this is correct?',
[email protected]06e6d0ff2012-12-11 01:36:441053 [' %s:%d: %s' % (
1054 problem[0], problem[1], problem[2]) for problem in problems])]
[email protected]2fdd1f362013-01-16 03:56:031055 else:
1056 return []
[email protected]06e6d0ff2012-12-11 01:36:441057
1058
[email protected]d2530012013-01-25 16:39:271059def _CheckNoAbbreviationInPngFileName(input_api, output_api):
1060 """Makes sure there are no abbreviations in the name of PNG files.
binji0dcdf342014-12-12 18:32:311061 The native_client_sdk directory is excluded because it has auto-generated PNG
1062 files for documentation.
[email protected]d2530012013-01-25 16:39:271063 """
[email protected]d2530012013-01-25 16:39:271064 errors = []
binji0dcdf342014-12-12 18:32:311065 white_list = (r'.*_[a-z]_.*\.png$|.*_[a-z]\.png$',)
1066 black_list = (r'^native_client_sdk[\\\/]',)
1067 file_filter = lambda f: input_api.FilterSourceFile(
1068 f, white_list=white_list, black_list=black_list)
1069 for f in input_api.AffectedFiles(include_deletes=False,
1070 file_filter=file_filter):
1071 errors.append(' %s' % f.LocalPath())
[email protected]d2530012013-01-25 16:39:271072
1073 results = []
1074 if errors:
1075 results.append(output_api.PresubmitError(
1076 'The name of PNG files should not have abbreviations. \n'
1077 'Use _hover.png, _center.png, instead of _h.png, _c.png.\n'
1078 'Contact [email protected] if you have questions.', errors))
1079 return results
1080
1081
sammcbe5ca3e2017-04-03 01:48:361082def _FilesToCheckForIncomingDeps(re, changed_lines):
[email protected]f32e2d1e2013-07-26 21:39:081083 """Helper method for _CheckAddedDepsHaveTargetApprovals. Returns
[email protected]14a6131c2014-01-08 01:15:411084 a set of DEPS entries that we should look up.
1085
1086 For a directory (rather than a specific filename) we fake a path to
1087 a specific filename by adding /DEPS. This is chosen as a file that
1088 will seldom or never be subject to per-file include_rules.
1089 """
[email protected]2b438d62013-11-14 17:54:141090 # We ignore deps entries on auto-generated directories.
1091 AUTO_GENERATED_DIRS = ['grit', 'jni']
[email protected]f32e2d1e2013-07-26 21:39:081092
sammcbe5ca3e2017-04-03 01:48:361093 # This pattern grabs the path without basename in the first
1094 # parentheses, and the basename (if present) in the second. It
1095 # relies on the simple heuristic that if there is a basename it will
1096 # be a header file ending in ".h".
1097 pattern = re.compile(
1098 r"""['"]\+([^'"]+?)(/[a-zA-Z0-9_]+\.h)?['"].*""")
[email protected]2b438d62013-11-14 17:54:141099 results = set()
sammcbe5ca3e2017-04-03 01:48:361100 for changed_line in changed_lines:
1101 m = pattern.match(changed_line)
1102 if m:
1103 path = m.group(1)
1104 if path.split('/')[0] not in AUTO_GENERATED_DIRS:
1105 if m.group(2):
1106 results.add('%s%s' % (path, m.group(2)))
1107 else:
1108 results.add('%s/DEPS' % path)
[email protected]f32e2d1e2013-07-26 21:39:081109 return results
1110
1111
[email protected]e871964c2013-05-13 14:14:551112def _CheckAddedDepsHaveTargetApprovals(input_api, output_api):
1113 """When a dependency prefixed with + is added to a DEPS file, we
1114 want to make sure that the change is reviewed by an OWNER of the
1115 target file or directory, to avoid layering violations from being
1116 introduced. This check verifies that this happens.
1117 """
sammcbe5ca3e2017-04-03 01:48:361118 changed_lines = set()
jochen53efcdd2016-01-29 05:09:241119
1120 file_filter = lambda f: not input_api.re.match(
1121 r"^third_party[\\\/]WebKit[\\\/].*", f.LocalPath())
1122 for f in input_api.AffectedFiles(include_deletes=False,
1123 file_filter=file_filter):
[email protected]e871964c2013-05-13 14:14:551124 filename = input_api.os_path.basename(f.LocalPath())
1125 if filename == 'DEPS':
sammcbe5ca3e2017-04-03 01:48:361126 changed_lines |= set(line.strip()
1127 for line_num, line
1128 in f.ChangedContents())
1129 if not changed_lines:
1130 return []
[email protected]e871964c2013-05-13 14:14:551131
sammcbe5ca3e2017-04-03 01:48:361132 virtual_depended_on_files = _FilesToCheckForIncomingDeps(input_api.re,
1133 changed_lines)
[email protected]e871964c2013-05-13 14:14:551134 if not virtual_depended_on_files:
1135 return []
1136
1137 if input_api.is_committing:
1138 if input_api.tbr:
1139 return [output_api.PresubmitNotifyResult(
1140 '--tbr was specified, skipping OWNERS check for DEPS additions')]
Paweł Hajdan, Jrbe6739ea2016-04-28 15:07:271141 if input_api.dry_run:
1142 return [output_api.PresubmitNotifyResult(
1143 'This is a dry run, skipping OWNERS check for DEPS additions')]
[email protected]e871964c2013-05-13 14:14:551144 if not input_api.change.issue:
1145 return [output_api.PresubmitError(
1146 "DEPS approval by OWNERS check failed: this change has "
1147 "no Rietveld issue number, so we can't check it for approvals.")]
1148 output = output_api.PresubmitError
1149 else:
1150 output = output_api.PresubmitNotifyResult
1151
1152 owners_db = input_api.owners_db
tandriied3b7e12016-05-12 14:38:501153 owner_email, reviewers = (
1154 input_api.canned_checks.GetCodereviewOwnerAndReviewers(
1155 input_api,
1156 owners_db.email_regexp,
1157 approval_needed=input_api.is_committing))
[email protected]e871964c2013-05-13 14:14:551158
1159 owner_email = owner_email or input_api.change.author_email
1160
[email protected]de4f7d22013-05-23 14:27:461161 reviewers_plus_owner = set(reviewers)
[email protected]e71c6082013-05-22 02:28:511162 if owner_email:
[email protected]de4f7d22013-05-23 14:27:461163 reviewers_plus_owner.add(owner_email)
[email protected]e871964c2013-05-13 14:14:551164 missing_files = owners_db.files_not_covered_by(virtual_depended_on_files,
1165 reviewers_plus_owner)
[email protected]14a6131c2014-01-08 01:15:411166
1167 # We strip the /DEPS part that was added by
1168 # _FilesToCheckForIncomingDeps to fake a path to a file in a
1169 # directory.
1170 def StripDeps(path):
1171 start_deps = path.rfind('/DEPS')
1172 if start_deps != -1:
1173 return path[:start_deps]
1174 else:
1175 return path
1176 unapproved_dependencies = ["'+%s'," % StripDeps(path)
[email protected]e871964c2013-05-13 14:14:551177 for path in missing_files]
1178
1179 if unapproved_dependencies:
1180 output_list = [
Paweł Hajdan, Jrec17f882016-07-04 14:16:151181 output('You need LGTM from owners of depends-on paths in DEPS that were '
1182 'modified in this CL:\n %s' %
1183 '\n '.join(sorted(unapproved_dependencies)))]
1184 suggested_owners = owners_db.reviewers_for(missing_files, owner_email)
1185 output_list.append(output(
1186 'Suggested missing target path OWNERS:\n %s' %
1187 '\n '.join(suggested_owners or [])))
[email protected]e871964c2013-05-13 14:14:551188 return output_list
1189
1190 return []
1191
1192
[email protected]85218562013-11-22 07:41:401193def _CheckSpamLogging(input_api, output_api):
1194 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
1195 black_list = (_EXCLUDED_PATHS +
1196 _TEST_CODE_EXCLUDED_PATHS +
1197 input_api.DEFAULT_BLACK_LIST +
[email protected]6f742dd02013-11-26 23:19:501198 (r"^base[\\\/]logging\.h$",
[email protected]80f360a2014-01-23 01:36:191199 r"^base[\\\/]logging\.cc$",
[email protected]8dc338c2013-12-09 16:28:481200 r"^chrome[\\\/]app[\\\/]chrome_main_delegate\.cc$",
[email protected]6e268db2013-12-04 01:41:461201 r"^chrome[\\\/]browser[\\\/]chrome_browser_main\.cc$",
[email protected]4de75262013-12-18 23:16:121202 r"^chrome[\\\/]browser[\\\/]ui[\\\/]startup[\\\/]"
1203 r"startup_browser_creator\.cc$",
[email protected]fe0e6e12013-12-04 05:52:581204 r"^chrome[\\\/]installer[\\\/]setup[\\\/].*",
[email protected]8cf6f842014-08-08 21:33:161205 r"chrome[\\\/]browser[\\\/]diagnostics[\\\/]" +
[email protected]f5b9a3f342014-08-08 22:06:031206 r"diagnostics_writer\.cc$",
[email protected]9f13b602014-08-07 02:59:151207 r"^chrome_elf[\\\/]dll_hash[\\\/]dll_hash_main\.cc$",
1208 r"^chromecast[\\\/]",
1209 r"^cloud_print[\\\/]",
jochen34415e52015-07-10 08:34:311210 r"^components[\\\/]html_viewer[\\\/]"
1211 r"web_test_delegate_impl\.cc$",
peter80739bb2015-10-20 11:17:461212 # TODO(peter): Remove this exception. https://crbug.com/534537
1213 r"^content[\\\/]browser[\\\/]notifications[\\\/]"
1214 r"notification_event_dispatcher_impl\.cc$",
[email protected]9056e732014-01-08 06:25:251215 r"^content[\\\/]common[\\\/]gpu[\\\/]client[\\\/]"
1216 r"gl_helper_benchmark\.cc$",
altimin979ea2e12016-05-18 16:16:241217 r"^courgette[\\\/]courgette_minimal_tool\.cc$",
thestigc9e38a22014-09-13 01:02:111218 r"^courgette[\\\/]courgette_tool\.cc$",
[email protected]9f13b602014-08-07 02:59:151219 r"^extensions[\\\/]renderer[\\\/]logging_native_handler\.cc$",
prashant.nb0252f62014-11-08 05:02:111220 r"^ipc[\\\/]ipc_logging\.cc$",
[email protected]9c36d922014-03-24 16:47:521221 r"^native_client_sdk[\\\/]",
[email protected]cdbdced2013-11-27 21:35:501222 r"^remoting[\\\/]base[\\\/]logging\.h$",
[email protected]67c96ab2013-12-17 02:05:361223 r"^remoting[\\\/]host[\\\/].*",
[email protected]8232f8fd2013-12-14 00:52:311224 r"^sandbox[\\\/]linux[\\\/].*",
[email protected]0b7a21e2014-02-11 18:38:131225 r"^tools[\\\/]",
asvitkine8a40fe5f02017-02-18 15:35:001226 r"^ui[\\\/]base[\\\/]resource[\\\/]data_pack.cc$",
thestig22dfc4012014-09-05 08:29:441227 r"^ui[\\\/]aura[\\\/]bench[\\\/]bench_main\.cc$",
halliwellf7fc61c62016-01-28 17:18:451228 r"^ui[\\\/]ozone[\\\/]platform[\\\/]cast[\\\/]",
vchigrin14251492015-01-12 08:09:021229 r"^storage[\\\/]browser[\\\/]fileapi[\\\/]" +
skyostil87681be82016-12-19 12:46:351230 r"dump_file_system.cc$",
1231 r"^headless[\\\/]app[\\\/]headless_shell\.cc$"))
[email protected]85218562013-11-22 07:41:401232 source_file_filter = lambda x: input_api.FilterSourceFile(
1233 x, white_list=(file_inclusion_pattern,), black_list=black_list)
1234
thomasanderson625d3932017-03-29 07:16:581235 log_info = set([])
1236 printf = set([])
[email protected]85218562013-11-22 07:41:401237
1238 for f in input_api.AffectedSourceFiles(source_file_filter):
thomasanderson625d3932017-03-29 07:16:581239 for _, line in f.ChangedContents():
1240 if input_api.re.search(r"\bD?LOG\s*\(\s*INFO\s*\)", line):
1241 log_info.add(f.LocalPath())
1242 elif input_api.re.search(r"\bD?LOG_IF\s*\(\s*INFO\s*,", line):
1243 log_info.add(f.LocalPath())
[email protected]18b466b2013-12-02 22:01:371244
thomasanderson625d3932017-03-29 07:16:581245 if input_api.re.search(r"\bprintf\(", line):
1246 printf.add(f.LocalPath())
1247 elif input_api.re.search(r"\bfprintf\((stdout|stderr)", line):
1248 printf.add(f.LocalPath())
[email protected]85218562013-11-22 07:41:401249
1250 if log_info:
1251 return [output_api.PresubmitError(
1252 'These files spam the console log with LOG(INFO):',
1253 items=log_info)]
1254 if printf:
1255 return [output_api.PresubmitError(
1256 'These files spam the console log with printf/fprintf:',
1257 items=printf)]
1258 return []
1259
1260
[email protected]49aa76a2013-12-04 06:59:161261def _CheckForAnonymousVariables(input_api, output_api):
1262 """These types are all expected to hold locks while in scope and
1263 so should never be anonymous (which causes them to be immediately
1264 destroyed)."""
1265 they_who_must_be_named = [
1266 'base::AutoLock',
1267 'base::AutoReset',
1268 'base::AutoUnlock',
1269 'SkAutoAlphaRestore',
1270 'SkAutoBitmapShaderInstall',
1271 'SkAutoBlitterChoose',
1272 'SkAutoBounderCommit',
1273 'SkAutoCallProc',
1274 'SkAutoCanvasRestore',
1275 'SkAutoCommentBlock',
1276 'SkAutoDescriptor',
1277 'SkAutoDisableDirectionCheck',
1278 'SkAutoDisableOvalCheck',
1279 'SkAutoFree',
1280 'SkAutoGlyphCache',
1281 'SkAutoHDC',
1282 'SkAutoLockColors',
1283 'SkAutoLockPixels',
1284 'SkAutoMalloc',
1285 'SkAutoMaskFreeImage',
1286 'SkAutoMutexAcquire',
1287 'SkAutoPathBoundsUpdate',
1288 'SkAutoPDFRelease',
1289 'SkAutoRasterClipValidate',
1290 'SkAutoRef',
1291 'SkAutoTime',
1292 'SkAutoTrace',
1293 'SkAutoUnref',
1294 ]
1295 anonymous = r'(%s)\s*[({]' % '|'.join(they_who_must_be_named)
1296 # bad: base::AutoLock(lock.get());
1297 # not bad: base::AutoLock lock(lock.get());
1298 bad_pattern = input_api.re.compile(anonymous)
1299 # good: new base::AutoLock(lock.get())
1300 good_pattern = input_api.re.compile(r'\bnew\s*' + anonymous)
1301 errors = []
1302
1303 for f in input_api.AffectedFiles():
1304 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
1305 continue
1306 for linenum, line in f.ChangedContents():
1307 if bad_pattern.search(line) and not good_pattern.search(line):
1308 errors.append('%s:%d' % (f.LocalPath(), linenum))
1309
1310 if errors:
1311 return [output_api.PresubmitError(
1312 'These lines create anonymous variables that need to be named:',
1313 items=errors)]
1314 return []
1315
1316
[email protected]5fe0f8742013-11-29 01:04:591317def _CheckCygwinShell(input_api, output_api):
1318 source_file_filter = lambda x: input_api.FilterSourceFile(
1319 x, white_list=(r'.+\.(gyp|gypi)$',))
1320 cygwin_shell = []
1321
1322 for f in input_api.AffectedSourceFiles(source_file_filter):
1323 for linenum, line in f.ChangedContents():
1324 if 'msvs_cygwin_shell' in line:
1325 cygwin_shell.append(f.LocalPath())
1326 break
1327
1328 if cygwin_shell:
1329 return [output_api.PresubmitError(
1330 'These files should not use msvs_cygwin_shell (the default is 0):',
1331 items=cygwin_shell)]
1332 return []
1333
[email protected]85218562013-11-22 07:41:401334
[email protected]999261d2014-03-03 20:08:081335def _CheckUserActionUpdate(input_api, output_api):
1336 """Checks if any new user action has been added."""
[email protected]2f92dec2014-03-07 19:21:521337 if any('actions.xml' == input_api.os_path.basename(f) for f in
[email protected]999261d2014-03-03 20:08:081338 input_api.LocalPaths()):
[email protected]2f92dec2014-03-07 19:21:521339 # If actions.xml is already included in the changelist, the PRESUBMIT
1340 # for actions.xml will do a more complete presubmit check.
[email protected]999261d2014-03-03 20:08:081341 return []
1342
[email protected]999261d2014-03-03 20:08:081343 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm'))
1344 action_re = r'[^a-zA-Z]UserMetricsAction\("([^"]*)'
[email protected]2f92dec2014-03-07 19:21:521345 current_actions = None
[email protected]999261d2014-03-03 20:08:081346 for f in input_api.AffectedFiles(file_filter=file_filter):
1347 for line_num, line in f.ChangedContents():
1348 match = input_api.re.search(action_re, line)
1349 if match:
[email protected]2f92dec2014-03-07 19:21:521350 # Loads contents in tools/metrics/actions/actions.xml to memory. It's
1351 # loaded only once.
1352 if not current_actions:
1353 with open('tools/metrics/actions/actions.xml') as actions_f:
1354 current_actions = actions_f.read()
1355 # Search for the matched user action name in |current_actions|.
[email protected]999261d2014-03-03 20:08:081356 for action_name in match.groups():
[email protected]2f92dec2014-03-07 19:21:521357 action = 'name="{0}"'.format(action_name)
1358 if action not in current_actions:
[email protected]999261d2014-03-03 20:08:081359 return [output_api.PresubmitPromptWarning(
1360 'File %s line %d: %s is missing in '
[email protected]2f92dec2014-03-07 19:21:521361 'tools/metrics/actions/actions.xml. Please run '
1362 'tools/metrics/actions/extract_actions.py to update.'
[email protected]999261d2014-03-03 20:08:081363 % (f.LocalPath(), line_num, action_name))]
1364 return []
1365
1366
[email protected]99171a92014-06-03 08:44:471367def _GetJSONParseError(input_api, filename, eat_comments=True):
1368 try:
1369 contents = input_api.ReadFile(filename)
1370 if eat_comments:
plundblad1f5a4509f2015-07-23 11:31:131371 import sys
1372 original_sys_path = sys.path
1373 try:
1374 sys.path = sys.path + [input_api.os_path.join(
1375 input_api.PresubmitLocalPath(),
1376 'tools', 'json_comment_eater')]
1377 import json_comment_eater
1378 finally:
1379 sys.path = original_sys_path
1380 contents = json_comment_eater.Nom(contents)
[email protected]99171a92014-06-03 08:44:471381
1382 input_api.json.loads(contents)
1383 except ValueError as e:
1384 return e
1385 return None
1386
1387
1388def _GetIDLParseError(input_api, filename):
1389 try:
1390 contents = input_api.ReadFile(filename)
1391 idl_schema = input_api.os_path.join(
1392 input_api.PresubmitLocalPath(),
1393 'tools', 'json_schema_compiler', 'idl_schema.py')
1394 process = input_api.subprocess.Popen(
1395 [input_api.python_executable, idl_schema],
1396 stdin=input_api.subprocess.PIPE,
1397 stdout=input_api.subprocess.PIPE,
1398 stderr=input_api.subprocess.PIPE,
1399 universal_newlines=True)
1400 (_, error) = process.communicate(input=contents)
1401 return error or None
1402 except ValueError as e:
1403 return e
1404
1405
1406def _CheckParseErrors(input_api, output_api):
1407 """Check that IDL and JSON files do not contain syntax errors."""
1408 actions = {
1409 '.idl': _GetIDLParseError,
1410 '.json': _GetJSONParseError,
1411 }
1412 # These paths contain test data and other known invalid JSON files.
1413 excluded_patterns = [
joaodasilva718f87672014-08-30 09:25:491414 r'test[\\\/]data[\\\/]',
1415 r'^components[\\\/]policy[\\\/]resources[\\\/]policy_templates\.json$',
[email protected]99171a92014-06-03 08:44:471416 ]
1417 # Most JSON files are preprocessed and support comments, but these do not.
1418 json_no_comments_patterns = [
joaodasilva718f87672014-08-30 09:25:491419 r'^testing[\\\/]',
[email protected]99171a92014-06-03 08:44:471420 ]
1421 # Only run IDL checker on files in these directories.
1422 idl_included_patterns = [
joaodasilva718f87672014-08-30 09:25:491423 r'^chrome[\\\/]common[\\\/]extensions[\\\/]api[\\\/]',
1424 r'^extensions[\\\/]common[\\\/]api[\\\/]',
[email protected]99171a92014-06-03 08:44:471425 ]
1426
1427 def get_action(affected_file):
1428 filename = affected_file.LocalPath()
1429 return actions.get(input_api.os_path.splitext(filename)[1])
1430
1431 def MatchesFile(patterns, path):
1432 for pattern in patterns:
1433 if input_api.re.search(pattern, path):
1434 return True
1435 return False
1436
1437 def FilterFile(affected_file):
1438 action = get_action(affected_file)
1439 if not action:
1440 return False
1441 path = affected_file.LocalPath()
1442
1443 if MatchesFile(excluded_patterns, path):
1444 return False
1445
1446 if (action == _GetIDLParseError and
1447 not MatchesFile(idl_included_patterns, path)):
1448 return False
1449 return True
1450
1451 results = []
1452 for affected_file in input_api.AffectedFiles(
1453 file_filter=FilterFile, include_deletes=False):
1454 action = get_action(affected_file)
1455 kwargs = {}
1456 if (action == _GetJSONParseError and
1457 MatchesFile(json_no_comments_patterns, affected_file.LocalPath())):
1458 kwargs['eat_comments'] = False
1459 parse_error = action(input_api,
1460 affected_file.AbsoluteLocalPath(),
1461 **kwargs)
1462 if parse_error:
1463 results.append(output_api.PresubmitError('%s could not be parsed: %s' %
1464 (affected_file.LocalPath(), parse_error)))
1465 return results
1466
1467
[email protected]760deea2013-12-10 19:33:491468def _CheckJavaStyle(input_api, output_api):
1469 """Runs checkstyle on changed java files and returns errors if any exist."""
mohan.reddyf21db962014-10-16 12:26:471470 import sys
[email protected]760deea2013-12-10 19:33:491471 original_sys_path = sys.path
1472 try:
1473 sys.path = sys.path + [input_api.os_path.join(
1474 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkstyle')]
1475 import checkstyle
1476 finally:
1477 # Restore sys.path to what it was before.
1478 sys.path = original_sys_path
1479
1480 return checkstyle.RunCheckstyle(
davileen72d76532015-01-20 22:30:091481 input_api, output_api, 'tools/android/checkstyle/chromium-style-5.0.xml',
newtd8b7d30e92015-01-23 18:10:511482 black_list=_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
[email protected]760deea2013-12-10 19:33:491483
1484
dchenge07de812016-06-20 19:27:171485def _CheckIpcOwners(input_api, output_api):
1486 """Checks that affected files involving IPC have an IPC OWNERS rule.
1487
1488 Whether or not a file affects IPC is determined by a simple whitelist of
1489 filename patterns."""
1490 file_patterns = [
palmerb19a0932017-01-24 04:00:311491 # Legacy IPC:
dchenge07de812016-06-20 19:27:171492 '*_messages.cc',
1493 '*_messages*.h',
1494 '*_param_traits*.*',
palmerb19a0932017-01-24 04:00:311495 # Mojo IPC:
dchenge07de812016-06-20 19:27:171496 '*.mojom',
1497 '*_struct_traits*.*',
1498 '*_type_converter*.*',
palmerb19a0932017-01-24 04:00:311499 '*.typemap',
1500 # Android native IPC:
1501 '*.aidl',
1502 # Blink uses a different file naming convention:
1503 '*EnumTraits*.*',
dchenge07de812016-06-20 19:27:171504 '*StructTraits*.*',
1505 '*TypeConverter*.*',
1506 ]
1507
scottmg7a6ed5ba2016-11-04 18:22:041508 # These third_party directories do not contain IPCs, but contain files
1509 # matching the above patterns, which trigger false positives.
1510 exclude_paths = [
1511 'third_party/crashpad/*',
1512 ]
1513
dchenge07de812016-06-20 19:27:171514 # Dictionary mapping an OWNERS file path to Patterns.
1515 # Patterns is a dictionary mapping glob patterns (suitable for use in per-file
1516 # rules ) to a PatternEntry.
1517 # PatternEntry is a dictionary with two keys:
1518 # - 'files': the files that are matched by this pattern
1519 # - 'rules': the per-file rules needed for this pattern
1520 # For example, if we expect OWNERS file to contain rules for *.mojom and
1521 # *_struct_traits*.*, Patterns might look like this:
1522 # {
1523 # '*.mojom': {
1524 # 'files': ...,
1525 # 'rules': [
1526 # 'per-file *.mojom=set noparent',
1527 # 'per-file *.mojom=file://ipc/SECURITY_OWNERS',
1528 # ],
1529 # },
1530 # '*_struct_traits*.*': {
1531 # 'files': ...,
1532 # 'rules': [
1533 # 'per-file *_struct_traits*.*=set noparent',
1534 # 'per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS',
1535 # ],
1536 # },
1537 # }
1538 to_check = {}
1539
1540 # Iterate through the affected files to see what we actually need to check
1541 # for. We should only nag patch authors about per-file rules if a file in that
1542 # directory would match that pattern. If a directory only contains *.mojom
1543 # files and no *_messages*.h files, we should only nag about rules for
1544 # *.mojom files.
rockot51249332016-06-23 16:32:251545 for f in input_api.change.AffectedFiles(include_deletes=False):
dchenge07de812016-06-20 19:27:171546 for pattern in file_patterns:
1547 if input_api.fnmatch.fnmatch(
1548 input_api.os_path.basename(f.LocalPath()), pattern):
scottmg7a6ed5ba2016-11-04 18:22:041549 skip = False
1550 for exclude in exclude_paths:
1551 if input_api.fnmatch.fnmatch(f.LocalPath(), exclude):
1552 skip = True
1553 break
1554 if skip:
1555 continue
dchenge07de812016-06-20 19:27:171556 owners_file = input_api.os_path.join(
1557 input_api.os_path.dirname(f.LocalPath()), 'OWNERS')
1558 if owners_file not in to_check:
1559 to_check[owners_file] = {}
1560 if pattern not in to_check[owners_file]:
1561 to_check[owners_file][pattern] = {
1562 'files': [],
1563 'rules': [
1564 'per-file %s=set noparent' % pattern,
1565 'per-file %s=file://ipc/SECURITY_OWNERS' % pattern,
1566 ]
1567 }
1568 to_check[owners_file][pattern]['files'].append(f)
1569 break
1570
1571 # Now go through the OWNERS files we collected, filtering out rules that are
1572 # already present in that OWNERS file.
1573 for owners_file, patterns in to_check.iteritems():
1574 try:
1575 with file(owners_file) as f:
1576 lines = set(f.read().splitlines())
1577 for entry in patterns.itervalues():
1578 entry['rules'] = [rule for rule in entry['rules'] if rule not in lines
1579 ]
1580 except IOError:
1581 # No OWNERS file, so all the rules are definitely missing.
1582 continue
1583
1584 # All the remaining lines weren't found in OWNERS files, so emit an error.
1585 errors = []
1586 for owners_file, patterns in to_check.iteritems():
1587 missing_lines = []
1588 files = []
1589 for pattern, entry in patterns.iteritems():
1590 missing_lines.extend(entry['rules'])
1591 files.extend([' %s' % f.LocalPath() for f in entry['files']])
1592 if missing_lines:
1593 errors.append(
1594 '%s is missing the following lines:\n\n%s\n\nfor changed files:\n%s' %
1595 (owners_file, '\n'.join(missing_lines), '\n'.join(files)))
1596
1597 results = []
1598 if errors:
vabrf5ce3bf92016-07-11 14:52:411599 if input_api.is_committing:
1600 output = output_api.PresubmitError
1601 else:
1602 output = output_api.PresubmitPromptWarning
1603 results.append(output(
dchenge07de812016-06-20 19:27:171604 'Found changes to IPC files without a security OWNER!',
1605 long_text='\n\n'.join(errors)))
1606
1607 return results
1608
1609
jbriance9e12f162016-11-25 07:57:501610def _CheckUselessForwardDeclarations(input_api, output_api):
jbriance2c51e821a2016-12-12 08:24:311611 """Checks that added or removed lines in non third party affected
1612 header files do not lead to new useless class or struct forward
1613 declaration.
jbriance9e12f162016-11-25 07:57:501614 """
1615 results = []
1616 class_pattern = input_api.re.compile(r'^class\s+(\w+);$',
1617 input_api.re.MULTILINE)
1618 struct_pattern = input_api.re.compile(r'^struct\s+(\w+);$',
1619 input_api.re.MULTILINE)
1620 for f in input_api.AffectedFiles(include_deletes=False):
jbriance2c51e821a2016-12-12 08:24:311621 if (f.LocalPath().startswith('third_party') and
1622 not f.LocalPath().startswith('third_party/WebKit') and
1623 not f.LocalPath().startswith('third_party\\WebKit')):
1624 continue
1625
jbriance9e12f162016-11-25 07:57:501626 if not f.LocalPath().endswith('.h'):
1627 continue
1628
1629 contents = input_api.ReadFile(f)
1630 fwd_decls = input_api.re.findall(class_pattern, contents)
1631 fwd_decls.extend(input_api.re.findall(struct_pattern, contents))
1632
1633 useless_fwd_decls = []
1634 for decl in fwd_decls:
1635 count = sum(1 for _ in input_api.re.finditer(
1636 r'\b%s\b' % input_api.re.escape(decl), contents))
1637 if count == 1:
1638 useless_fwd_decls.append(decl)
1639
1640 if not useless_fwd_decls:
1641 continue
1642
1643 for line in f.GenerateScmDiff().splitlines():
1644 if (line.startswith('-') and not line.startswith('--') or
1645 line.startswith('+') and not line.startswith('++')):
1646 for decl in useless_fwd_decls:
1647 if input_api.re.search(r'\b%s\b' % decl, line[1:]):
1648 results.append(output_api.PresubmitPromptWarning(
1649 '%s: %s forward declaration is becoming useless' %
1650 (f.LocalPath(), decl)))
1651 useless_fwd_decls.remove(decl)
1652
1653 return results
1654
1655
dskiba88634f4e2015-08-14 23:03:291656def _CheckAndroidToastUsage(input_api, output_api):
1657 """Checks that code uses org.chromium.ui.widget.Toast instead of
1658 android.widget.Toast (Chromium Toast doesn't force hardware
1659 acceleration on low-end devices, saving memory).
1660 """
1661 toast_import_pattern = input_api.re.compile(
1662 r'^import android\.widget\.Toast;$')
1663
1664 errors = []
1665
1666 sources = lambda affected_file: input_api.FilterSourceFile(
1667 affected_file,
1668 black_list=(_EXCLUDED_PATHS +
1669 _TEST_CODE_EXCLUDED_PATHS +
1670 input_api.DEFAULT_BLACK_LIST +
1671 (r'^chromecast[\\\/].*',
1672 r'^remoting[\\\/].*')),
1673 white_list=(r'.*\.java$',))
1674
1675 for f in input_api.AffectedSourceFiles(sources):
1676 for line_num, line in f.ChangedContents():
1677 if toast_import_pattern.search(line):
1678 errors.append("%s:%d" % (f.LocalPath(), line_num))
1679
1680 results = []
1681
1682 if errors:
1683 results.append(output_api.PresubmitError(
1684 'android.widget.Toast usage is detected. Android toasts use hardware'
1685 ' acceleration, and can be\ncostly on low-end devices. Please use'
1686 ' org.chromium.ui.widget.Toast instead.\n'
1687 'Contact [email protected] if you have any questions.',
1688 errors))
1689
1690 return results
1691
1692
dgnaa68d5e2015-06-10 10:08:221693def _CheckAndroidCrLogUsage(input_api, output_api):
1694 """Checks that new logs using org.chromium.base.Log:
1695 - Are using 'TAG' as variable name for the tags (warn)
dgn38736db2015-09-18 19:20:511696 - Are using a tag that is shorter than 20 characters (error)
dgnaa68d5e2015-06-10 10:08:221697 """
pkotwicza1dd0b002016-05-16 14:41:041698
torne89540622017-03-24 19:41:301699 # Do not check format of logs in the given files
pkotwicza1dd0b002016-05-16 14:41:041700 cr_log_check_excluded_paths = [
torne89540622017-03-24 19:41:301701 # //chrome/android/webapk cannot depend on //base
pkotwicza1dd0b002016-05-16 14:41:041702 r"^chrome[\\\/]android[\\\/]webapk[\\\/].*",
torne89540622017-03-24 19:41:301703 # WebView license viewer code cannot depend on //base; used in stub APK.
1704 r"^android_webview[\\\/]glue[\\\/]java[\\\/]src[\\\/]com[\\\/]android[\\\/]"
1705 r"webview[\\\/]chromium[\\\/]License.*",
pkotwicza1dd0b002016-05-16 14:41:041706 ]
1707
dgnaa68d5e2015-06-10 10:08:221708 cr_log_import_pattern = input_api.re.compile(
dgn87d9fb62015-06-12 09:15:121709 r'^import org\.chromium\.base\.Log;$', input_api.re.MULTILINE)
1710 class_in_base_pattern = input_api.re.compile(
1711 r'^package org\.chromium\.base;$', input_api.re.MULTILINE)
1712 has_some_log_import_pattern = input_api.re.compile(
1713 r'^import .*\.Log;$', input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221714 # Extract the tag from lines like `Log.d(TAG, "*");` or `Log.d("TAG", "*");`
dgn87d9fb62015-06-12 09:15:121715 log_call_pattern = input_api.re.compile(r'^\s*Log\.\w\((?P<tag>\"?\w+\"?)\,')
dgnaa68d5e2015-06-10 10:08:221716 log_decl_pattern = input_api.re.compile(
dgn38736db2015-09-18 19:20:511717 r'^\s*private static final String TAG = "(?P<name>(.*))";',
dgnaa68d5e2015-06-10 10:08:221718 input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221719
Vincent Scheib16d7b272015-09-15 18:09:071720 REF_MSG = ('See docs/android_logging.md '
dgnaa68d5e2015-06-10 10:08:221721 'or contact [email protected] for more info.')
pkotwicza1dd0b002016-05-16 14:41:041722 sources = lambda x: input_api.FilterSourceFile(x, white_list=(r'.*\.java$',),
1723 black_list=cr_log_check_excluded_paths)
dgn87d9fb62015-06-12 09:15:121724
dgnaa68d5e2015-06-10 10:08:221725 tag_decl_errors = []
1726 tag_length_errors = []
dgn87d9fb62015-06-12 09:15:121727 tag_errors = []
dgn38736db2015-09-18 19:20:511728 tag_with_dot_errors = []
dgn87d9fb62015-06-12 09:15:121729 util_log_errors = []
dgnaa68d5e2015-06-10 10:08:221730
1731 for f in input_api.AffectedSourceFiles(sources):
1732 file_content = input_api.ReadFile(f)
1733 has_modified_logs = False
1734
1735 # Per line checks
dgn87d9fb62015-06-12 09:15:121736 if (cr_log_import_pattern.search(file_content) or
1737 (class_in_base_pattern.search(file_content) and
1738 not has_some_log_import_pattern.search(file_content))):
1739 # Checks to run for files using cr log
dgnaa68d5e2015-06-10 10:08:221740 for line_num, line in f.ChangedContents():
1741
1742 # Check if the new line is doing some logging
dgn87d9fb62015-06-12 09:15:121743 match = log_call_pattern.search(line)
dgnaa68d5e2015-06-10 10:08:221744 if match:
1745 has_modified_logs = True
1746
1747 # Make sure it uses "TAG"
1748 if not match.group('tag') == 'TAG':
1749 tag_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgn87d9fb62015-06-12 09:15:121750 else:
1751 # Report non cr Log function calls in changed lines
1752 for line_num, line in f.ChangedContents():
1753 if log_call_pattern.search(line):
1754 util_log_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgnaa68d5e2015-06-10 10:08:221755
1756 # Per file checks
1757 if has_modified_logs:
1758 # Make sure the tag is using the "cr" prefix and is not too long
1759 match = log_decl_pattern.search(file_content)
dgn38736db2015-09-18 19:20:511760 tag_name = match.group('name') if match else None
1761 if not tag_name:
dgnaa68d5e2015-06-10 10:08:221762 tag_decl_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511763 elif len(tag_name) > 20:
dgnaa68d5e2015-06-10 10:08:221764 tag_length_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511765 elif '.' in tag_name:
1766 tag_with_dot_errors.append(f.LocalPath())
dgnaa68d5e2015-06-10 10:08:221767
1768 results = []
1769 if tag_decl_errors:
1770 results.append(output_api.PresubmitPromptWarning(
1771 'Please define your tags using the suggested format: .\n'
dgn38736db2015-09-18 19:20:511772 '"private static final String TAG = "<package tag>".\n'
1773 'They will be prepended with "cr_" automatically.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221774 tag_decl_errors))
1775
1776 if tag_length_errors:
1777 results.append(output_api.PresubmitError(
1778 'The tag length is restricted by the system to be at most '
dgn38736db2015-09-18 19:20:511779 '20 characters.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221780 tag_length_errors))
1781
1782 if tag_errors:
1783 results.append(output_api.PresubmitPromptWarning(
1784 'Please use a variable named "TAG" for your log tags.\n' + REF_MSG,
1785 tag_errors))
1786
dgn87d9fb62015-06-12 09:15:121787 if util_log_errors:
dgn4401aa52015-04-29 16:26:171788 results.append(output_api.PresubmitPromptWarning(
dgn87d9fb62015-06-12 09:15:121789 'Please use org.chromium.base.Log for new logs.\n' + REF_MSG,
1790 util_log_errors))
1791
dgn38736db2015-09-18 19:20:511792 if tag_with_dot_errors:
1793 results.append(output_api.PresubmitPromptWarning(
1794 'Dot in log tags cause them to be elided in crash reports.\n' + REF_MSG,
1795 tag_with_dot_errors))
1796
dgn4401aa52015-04-29 16:26:171797 return results
1798
1799
yolandyan45001472016-12-21 21:12:421800def _CheckAndroidTestAnnotationUsage(input_api, output_api):
1801 """Checks that android.test.suitebuilder.annotation.* is no longer used."""
1802 deprecated_annotation_import_pattern = input_api.re.compile(
1803 r'^import android\.test\.suitebuilder\.annotation\..*;',
1804 input_api.re.MULTILINE)
1805 sources = lambda x: input_api.FilterSourceFile(
1806 x, white_list=(r'.*\.java$',), black_list=None)
1807 errors = []
1808 for f in input_api.AffectedFiles(sources):
1809 for line_num, line in f.ChangedContents():
1810 if deprecated_annotation_import_pattern.search(line):
1811 errors.append("%s:%d" % (f.LocalPath(), line_num))
1812
1813 results = []
1814 if errors:
1815 results.append(output_api.PresubmitError(
1816 'Annotations in android.test.suitebuilder.annotation have been'
1817 ' deprecated since API level 24. Please use android.support.test.filters'
1818 ' from //third_party/android_support_test_runner:runner_java instead.'
1819 ' Contact [email protected] if you have any questions.', errors))
1820 return results
1821
1822
agrieve7b6479d82015-10-07 14:24:221823def _CheckAndroidNewMdpiAssetLocation(input_api, output_api):
1824 """Checks if MDPI assets are placed in a correct directory."""
1825 file_filter = lambda f: (f.LocalPath().endswith('.png') and
1826 ('/res/drawable/' in f.LocalPath() or
1827 '/res/drawable-ldrtl/' in f.LocalPath()))
1828 errors = []
1829 for f in input_api.AffectedFiles(include_deletes=False,
1830 file_filter=file_filter):
1831 errors.append(' %s' % f.LocalPath())
1832
1833 results = []
1834 if errors:
1835 results.append(output_api.PresubmitError(
1836 'MDPI assets should be placed in /res/drawable-mdpi/ or '
1837 '/res/drawable-ldrtl-mdpi/\ninstead of /res/drawable/ and'
1838 '/res/drawable-ldrtl/.\n'
1839 'Contact [email protected] if you have questions.', errors))
1840 return results
1841
1842
agrievef32bcc72016-04-04 14:57:401843class PydepsChecker(object):
1844 def __init__(self, input_api, pydeps_files):
1845 self._file_cache = {}
1846 self._input_api = input_api
1847 self._pydeps_files = pydeps_files
1848
1849 def _LoadFile(self, path):
1850 """Returns the list of paths within a .pydeps file relative to //."""
1851 if path not in self._file_cache:
1852 with open(path) as f:
1853 self._file_cache[path] = f.read()
1854 return self._file_cache[path]
1855
1856 def _ComputeNormalizedPydepsEntries(self, pydeps_path):
1857 """Returns an interable of paths within the .pydep, relativized to //."""
1858 os_path = self._input_api.os_path
1859 pydeps_dir = os_path.dirname(pydeps_path)
1860 entries = (l.rstrip() for l in self._LoadFile(pydeps_path).splitlines()
1861 if not l.startswith('*'))
1862 return (os_path.normpath(os_path.join(pydeps_dir, e)) for e in entries)
1863
1864 def _CreateFilesToPydepsMap(self):
1865 """Returns a map of local_path -> list_of_pydeps."""
1866 ret = {}
1867 for pydep_local_path in self._pydeps_files:
1868 for path in self._ComputeNormalizedPydepsEntries(pydep_local_path):
1869 ret.setdefault(path, []).append(pydep_local_path)
1870 return ret
1871
1872 def ComputeAffectedPydeps(self):
1873 """Returns an iterable of .pydeps files that might need regenerating."""
1874 affected_pydeps = set()
1875 file_to_pydeps_map = None
1876 for f in self._input_api.AffectedFiles(include_deletes=True):
1877 local_path = f.LocalPath()
1878 if local_path == 'DEPS':
1879 return self._pydeps_files
1880 elif local_path.endswith('.pydeps'):
1881 if local_path in self._pydeps_files:
1882 affected_pydeps.add(local_path)
1883 elif local_path.endswith('.py'):
1884 if file_to_pydeps_map is None:
1885 file_to_pydeps_map = self._CreateFilesToPydepsMap()
1886 affected_pydeps.update(file_to_pydeps_map.get(local_path, ()))
1887 return affected_pydeps
1888
1889 def DetermineIfStale(self, pydeps_path):
1890 """Runs print_python_deps.py to see if the files is stale."""
phajdan.jr0d9878552016-11-04 10:49:411891 import difflib
agrievef32bcc72016-04-04 14:57:401892 old_pydeps_data = self._LoadFile(pydeps_path).splitlines()
1893 cmd = old_pydeps_data[1][1:].strip()
1894 new_pydeps_data = self._input_api.subprocess.check_output(
1895 cmd + ' --output ""', shell=True)
phajdan.jr0d9878552016-11-04 10:49:411896 old_contents = old_pydeps_data[2:]
1897 new_contents = new_pydeps_data.splitlines()[2:]
agrievef32bcc72016-04-04 14:57:401898 if old_pydeps_data[2:] != new_pydeps_data.splitlines()[2:]:
phajdan.jr0d9878552016-11-04 10:49:411899 return cmd, '\n'.join(difflib.context_diff(old_contents, new_contents))
agrievef32bcc72016-04-04 14:57:401900
1901
1902def _CheckPydepsNeedsUpdating(input_api, output_api, checker_for_tests=None):
1903 """Checks if a .pydeps file needs to be regenerated."""
agrievebb9c5b472016-04-22 15:13:001904 # This check is mainly for Android, and involves paths not only in the
agrieve9bc4200b2016-05-04 16:33:281905 # PRESUBMIT.py, but also in the .pydeps files. It doesn't work on Windows and
1906 # Mac, so skip it on other platforms.
1907 if input_api.platform != 'linux2':
agrievebb9c5b472016-04-22 15:13:001908 return []
agrievef32bcc72016-04-04 14:57:401909 # TODO(agrieve): Update when there's a better way to detect this: crbug/570091
1910 is_android = input_api.os_path.exists('third_party/android_tools')
1911 pydeps_files = _ALL_PYDEPS_FILES if is_android else _GENERIC_PYDEPS_FILES
1912 results = []
1913 # First, check for new / deleted .pydeps.
1914 for f in input_api.AffectedFiles(include_deletes=True):
1915 if f.LocalPath().endswith('.pydeps'):
1916 if f.Action() == 'D' and f.LocalPath() in _ALL_PYDEPS_FILES:
1917 results.append(output_api.PresubmitError(
1918 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
1919 'remove %s' % f.LocalPath()))
1920 elif f.Action() != 'D' and f.LocalPath() not in _ALL_PYDEPS_FILES:
1921 results.append(output_api.PresubmitError(
1922 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
1923 'include %s' % f.LocalPath()))
1924
1925 if results:
1926 return results
1927
1928 checker = checker_for_tests or PydepsChecker(input_api, pydeps_files)
1929
1930 for pydep_path in checker.ComputeAffectedPydeps():
1931 try:
phajdan.jr0d9878552016-11-04 10:49:411932 result = checker.DetermineIfStale(pydep_path)
1933 if result:
1934 cmd, diff = result
agrievef32bcc72016-04-04 14:57:401935 results.append(output_api.PresubmitError(
phajdan.jr0d9878552016-11-04 10:49:411936 'File is stale: %s\nDiff (apply to fix):\n%s\n'
1937 'To regenerate, run:\n\n %s' %
1938 (pydep_path, diff, cmd)))
agrievef32bcc72016-04-04 14:57:401939 except input_api.subprocess.CalledProcessError as error:
1940 return [output_api.PresubmitError('Error running: %s' % error.cmd,
1941 long_text=error.output)]
1942
1943 return results
1944
1945
glidere61efad2015-02-18 17:39:431946def _CheckSingletonInHeaders(input_api, output_api):
1947 """Checks to make sure no header files have |Singleton<|."""
1948 def FileFilter(affected_file):
1949 # It's ok for base/memory/singleton.h to have |Singleton<|.
1950 black_list = (_EXCLUDED_PATHS +
1951 input_api.DEFAULT_BLACK_LIST +
1952 (r"^base[\\\/]memory[\\\/]singleton\.h$",))
1953 return input_api.FilterSourceFile(affected_file, black_list=black_list)
1954
sergeyu34d21222015-09-16 00:11:441955 pattern = input_api.re.compile(r'(?<!class\sbase::)Singleton\s*<')
glidere61efad2015-02-18 17:39:431956 files = []
1957 for f in input_api.AffectedSourceFiles(FileFilter):
1958 if (f.LocalPath().endswith('.h') or f.LocalPath().endswith('.hxx') or
1959 f.LocalPath().endswith('.hpp') or f.LocalPath().endswith('.inl')):
1960 contents = input_api.ReadFile(f)
1961 for line in contents.splitlines(False):
oysteinec430ad42015-10-22 20:55:241962 if (not line.lstrip().startswith('//') and # Strip C++ comment.
glidere61efad2015-02-18 17:39:431963 pattern.search(line)):
1964 files.append(f)
1965 break
1966
1967 if files:
yolandyandaabc6d2016-04-18 18:29:391968 return [output_api.PresubmitError(
sergeyu34d21222015-09-16 00:11:441969 'Found base::Singleton<T> in the following header files.\n' +
glidere61efad2015-02-18 17:39:431970 'Please move them to an appropriate source file so that the ' +
1971 'template gets instantiated in a single compilation unit.',
1972 files) ]
1973 return []
1974
1975
dbeam1ec68ac2016-12-15 05:22:241976def _CheckNoDeprecatedCompiledResourcesGyp(input_api, output_api):
dbeam37e8e7402016-02-10 22:58:201977 """Checks for old style compiled_resources.gyp files."""
1978 is_compiled_resource = lambda fp: fp.endswith('compiled_resources.gyp')
1979
1980 added_compiled_resources = filter(is_compiled_resource, [
1981 f.LocalPath() for f in input_api.AffectedFiles() if f.Action() == 'A'
1982 ])
1983
1984 if not added_compiled_resources:
1985 return []
1986
1987 return [output_api.PresubmitError(
1988 "Found new compiled_resources.gyp files:\n%s\n\n"
1989 "compiled_resources.gyp files are deprecated,\n"
michaelpgdb9985072016-02-24 19:13:551990 "please use compiled_resources2.gyp instead:\n"
1991 "https://chromium.googlesource.com/chromium/src/+/master/docs/closure_compilation.md"
1992 %
dbeam37e8e7402016-02-10 22:58:201993 "\n".join(added_compiled_resources))]
1994
1995
[email protected]fd20b902014-05-09 02:14:531996_DEPRECATED_CSS = [
1997 # Values
1998 ( "-webkit-box", "flex" ),
1999 ( "-webkit-inline-box", "inline-flex" ),
2000 ( "-webkit-flex", "flex" ),
2001 ( "-webkit-inline-flex", "inline-flex" ),
2002 ( "-webkit-min-content", "min-content" ),
2003 ( "-webkit-max-content", "max-content" ),
2004
2005 # Properties
2006 ( "-webkit-background-clip", "background-clip" ),
2007 ( "-webkit-background-origin", "background-origin" ),
2008 ( "-webkit-background-size", "background-size" ),
2009 ( "-webkit-box-shadow", "box-shadow" ),
dbeam6936c67f2017-01-19 01:51:442010 ( "-webkit-user-select", "user-select" ),
[email protected]fd20b902014-05-09 02:14:532011
2012 # Functions
2013 ( "-webkit-gradient", "gradient" ),
2014 ( "-webkit-repeating-gradient", "repeating-gradient" ),
2015 ( "-webkit-linear-gradient", "linear-gradient" ),
2016 ( "-webkit-repeating-linear-gradient", "repeating-linear-gradient" ),
2017 ( "-webkit-radial-gradient", "radial-gradient" ),
2018 ( "-webkit-repeating-radial-gradient", "repeating-radial-gradient" ),
2019]
2020
dbeam1ec68ac2016-12-15 05:22:242021def _CheckNoDeprecatedCss(input_api, output_api):
[email protected]fd20b902014-05-09 02:14:532022 """ Make sure that we don't use deprecated CSS
[email protected]9a48e3f82014-05-22 00:06:252023 properties, functions or values. Our external
mdjonesae0286c32015-06-10 18:10:342024 documentation and iOS CSS for dom distiller
2025 (reader mode) are ignored by the hooks as it
[email protected]9a48e3f82014-05-22 00:06:252026 needs to be consumed by WebKit. """
[email protected]fd20b902014-05-09 02:14:532027 results = []
dbeam070cfe62014-10-22 06:44:022028 file_inclusion_pattern = (r".+\.css$",)
[email protected]9a48e3f82014-05-22 00:06:252029 black_list = (_EXCLUDED_PATHS +
2030 _TEST_CODE_EXCLUDED_PATHS +
2031 input_api.DEFAULT_BLACK_LIST +
2032 (r"^chrome/common/extensions/docs",
2033 r"^chrome/docs",
mdjonesae0286c32015-06-10 18:10:342034 r"^components/dom_distiller/core/css/distilledpage_ios.css",
sdefresneda218472015-12-07 18:38:052035 r"^components/flags_ui/resources/apple_flags.css",
sdefresne6308d7f2016-02-15 09:38:442036 r"^components/neterror/resources/neterror.css",
[email protected]9a48e3f82014-05-22 00:06:252037 r"^native_client_sdk"))
2038 file_filter = lambda f: input_api.FilterSourceFile(
2039 f, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]fd20b902014-05-09 02:14:532040 for fpath in input_api.AffectedFiles(file_filter=file_filter):
2041 for line_num, line in fpath.ChangedContents():
2042 for (deprecated_value, value) in _DEPRECATED_CSS:
dbeam070cfe62014-10-22 06:44:022043 if deprecated_value in line:
[email protected]fd20b902014-05-09 02:14:532044 results.append(output_api.PresubmitError(
2045 "%s:%d: Use of deprecated CSS %s, use %s instead" %
2046 (fpath.LocalPath(), line_num, deprecated_value, value)))
2047 return results
2048
mohan.reddyf21db962014-10-16 12:26:472049
dbeam070cfe62014-10-22 06:44:022050_DEPRECATED_JS = [
2051 ( "__lookupGetter__", "Object.getOwnPropertyDescriptor" ),
2052 ( "__defineGetter__", "Object.defineProperty" ),
2053 ( "__defineSetter__", "Object.defineProperty" ),
2054]
2055
dbeam1ec68ac2016-12-15 05:22:242056def _CheckNoDeprecatedJs(input_api, output_api):
dbeam070cfe62014-10-22 06:44:022057 """Make sure that we don't use deprecated JS in Chrome code."""
2058 results = []
2059 file_inclusion_pattern = (r".+\.js$",) # TODO(dbeam): .html?
2060 black_list = (_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
2061 input_api.DEFAULT_BLACK_LIST)
2062 file_filter = lambda f: input_api.FilterSourceFile(
2063 f, white_list=file_inclusion_pattern, black_list=black_list)
2064 for fpath in input_api.AffectedFiles(file_filter=file_filter):
2065 for lnum, line in fpath.ChangedContents():
2066 for (deprecated, replacement) in _DEPRECATED_JS:
2067 if deprecated in line:
2068 results.append(output_api.PresubmitError(
2069 "%s:%d: Use of deprecated JS %s, use %s instead" %
2070 (fpath.LocalPath(), lnum, deprecated, replacement)))
2071 return results
2072
2073
dbeam1ec68ac2016-12-15 05:22:242074def _CheckForRiskyJsFeatures(input_api, output_api):
2075 maybe_ios_js = (r"^(ios|components|ui\/webui\/resources)\/.+\.js$", )
2076 file_filter = lambda f: input_api.FilterSourceFile(f, white_list=maybe_ios_js)
2077
2078 arrow_lines = []
2079 for f in input_api.AffectedFiles(file_filter=file_filter):
2080 for lnum, line in f.ChangedContents():
2081 if ' => ' in line:
2082 arrow_lines.append((f.LocalPath(), lnum))
2083
2084 if not arrow_lines:
2085 return []
2086
2087 return [output_api.PresubmitPromptWarning("""
2088Use of => operator detected in:
2089%s
2090Please ensure your code does not run on iOS9 (=> (arrow) does not work there).
2091https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#Arrow-Functions
2092""" % "\n".join(" %s:%d\n" % line for line in arrow_lines))]
2093
2094
dgnaa68d5e2015-06-10 10:08:222095def _AndroidSpecificOnUploadChecks(input_api, output_api):
2096 """Groups checks that target android code."""
2097 results = []
dgnaa68d5e2015-06-10 10:08:222098 results.extend(_CheckAndroidCrLogUsage(input_api, output_api))
agrieve7b6479d82015-10-07 14:24:222099 results.extend(_CheckAndroidNewMdpiAssetLocation(input_api, output_api))
dskiba88634f4e2015-08-14 23:03:292100 results.extend(_CheckAndroidToastUsage(input_api, output_api))
yolandyan45001472016-12-21 21:12:422101 results.extend(_CheckAndroidTestAnnotationUsage(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:222102 return results
2103
2104
[email protected]22c9bd72011-03-27 16:47:392105def _CommonChecks(input_api, output_api):
2106 """Checks common to both upload and commit."""
2107 results = []
2108 results.extend(input_api.canned_checks.PanProjectChecks(
[email protected]3de922f2013-12-20 13:27:382109 input_api, output_api,
qyearsleyfa2cfcf82016-12-15 18:03:542110 excluded_paths=_EXCLUDED_PATHS))
machenbachfbda9b72016-12-06 13:13:582111 results.extend(
2112 input_api.canned_checks.CheckAuthorizedAuthor(input_api, output_api))
[email protected]55459852011-08-10 15:17:192113 results.extend(
[email protected]760deea2013-12-10 19:33:492114 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api))
[email protected]10689ca2011-09-02 02:31:542115 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
[email protected]72df4e782012-06-21 16:28:182116 results.extend(_CheckNoUNIT_TESTInSourceFiles(input_api, output_api))
danakj61c1aa22015-10-26 19:55:522117 results.extend(_CheckDCHECK_IS_ONHasBraces(input_api, output_api))
[email protected]8ea5d4b2011-09-13 21:49:222118 results.extend(_CheckNoNewWStrings(input_api, output_api))
[email protected]2a8ac9c2011-10-19 17:20:442119 results.extend(_CheckNoDEPSGIT(input_api, output_api))
[email protected]127f18ec2012-06-16 05:05:592120 results.extend(_CheckNoBannedFunctions(input_api, output_api))
[email protected]6c063c62012-07-11 19:11:062121 results.extend(_CheckNoPragmaOnce(input_api, output_api))
[email protected]e7479052012-09-19 00:26:122122 results.extend(_CheckNoTrinaryTrueFalse(input_api, output_api))
[email protected]55f9f382012-07-31 11:02:182123 results.extend(_CheckUnwantedDependencies(input_api, output_api))
[email protected]fbcafe5a2012-08-08 15:31:222124 results.extend(_CheckFilePermissions(input_api, output_api))
robertocn832f5992017-01-04 19:01:302125 results.extend(_CheckTeamTags(input_api, output_api))
[email protected]c8278b32012-10-30 20:35:492126 results.extend(_CheckNoAuraWindowPropertyHInHeaders(input_api, output_api))
[email protected]2309b0fa02012-11-16 12:18:272127 results.extend(_CheckIncludeOrder(input_api, output_api))
[email protected]70ca77752012-11-20 03:45:032128 results.extend(_CheckForVersionControlConflicts(input_api, output_api))
[email protected]b8079ae4a2012-12-05 19:56:492129 results.extend(_CheckPatchFiles(input_api, output_api))
[email protected]06e6d0ff2012-12-11 01:36:442130 results.extend(_CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api))
[email protected]d2530012013-01-25 16:39:272131 results.extend(_CheckNoAbbreviationInPngFileName(input_api, output_api))
[email protected]b00342e7f2013-03-26 16:21:542132 results.extend(_CheckForInvalidOSMacros(input_api, output_api))
lliabraa35bab3932014-10-01 12:16:442133 results.extend(_CheckForInvalidIfDefinedMacros(input_api, output_api))
yolandyandaabc6d2016-04-18 18:29:392134 results.extend(_CheckFlakyTestUsage(input_api, output_api))
[email protected]e871964c2013-05-13 14:14:552135 results.extend(_CheckAddedDepsHaveTargetApprovals(input_api, output_api))
[email protected]9f919cc2013-07-31 03:04:042136 results.extend(
2137 input_api.canned_checks.CheckChangeHasNoTabs(
2138 input_api,
2139 output_api,
2140 source_file_filter=lambda x: x.LocalPath().endswith('.grd')))
[email protected]85218562013-11-22 07:41:402141 results.extend(_CheckSpamLogging(input_api, output_api))
[email protected]49aa76a2013-12-04 06:59:162142 results.extend(_CheckForAnonymousVariables(input_api, output_api))
[email protected]5fe0f8742013-11-29 01:04:592143 results.extend(_CheckCygwinShell(input_api, output_api))
[email protected]999261d2014-03-03 20:08:082144 results.extend(_CheckUserActionUpdate(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:242145 results.extend(_CheckNoDeprecatedCss(input_api, output_api))
2146 results.extend(_CheckNoDeprecatedJs(input_api, output_api))
[email protected]99171a92014-06-03 08:44:472147 results.extend(_CheckParseErrors(input_api, output_api))
mlamouria82272622014-09-16 18:45:042148 results.extend(_CheckForIPCRules(input_api, output_api))
mostynbb639aca52015-01-07 20:31:232149 results.extend(_CheckForWindowsLineEndings(input_api, output_api))
glidere61efad2015-02-18 17:39:432150 results.extend(_CheckSingletonInHeaders(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:242151 results.extend(_CheckNoDeprecatedCompiledResourcesGyp(input_api, output_api))
agrievef32bcc72016-04-04 14:57:402152 results.extend(_CheckPydepsNeedsUpdating(input_api, output_api))
wnwenbdc444e2016-05-25 13:44:152153 results.extend(_CheckJavaStyle(input_api, output_api))
dchenge07de812016-06-20 19:27:172154 results.extend(_CheckIpcOwners(input_api, output_api))
jbriance9e12f162016-11-25 07:57:502155 results.extend(_CheckUselessForwardDeclarations(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:242156 results.extend(_CheckForRiskyJsFeatures(input_api, output_api))
[email protected]2299dcf2012-11-15 19:56:242157
2158 if any('PRESUBMIT.py' == f.LocalPath() for f in input_api.AffectedFiles()):
2159 results.extend(input_api.canned_checks.RunUnitTestsInDirectory(
2160 input_api, output_api,
2161 input_api.PresubmitLocalPath(),
[email protected]6be63382013-01-21 15:42:382162 whitelist=[r'^PRESUBMIT_test\.py$']))
[email protected]22c9bd72011-03-27 16:47:392163 return results
[email protected]1f7b4172010-01-28 01:17:342164
[email protected]b337cb5b2011-01-23 21:24:052165
[email protected]b8079ae4a2012-12-05 19:56:492166def _CheckPatchFiles(input_api, output_api):
2167 problems = [f.LocalPath() for f in input_api.AffectedFiles()
2168 if f.LocalPath().endswith(('.orig', '.rej'))]
2169 if problems:
2170 return [output_api.PresubmitError(
2171 "Don't commit .rej and .orig files.", problems)]
[email protected]2fdd1f362013-01-16 03:56:032172 else:
2173 return []
[email protected]b8079ae4a2012-12-05 19:56:492174
2175
[email protected]b00342e7f2013-03-26 16:21:542176def _DidYouMeanOSMacro(bad_macro):
2177 try:
2178 return {'A': 'OS_ANDROID',
2179 'B': 'OS_BSD',
2180 'C': 'OS_CHROMEOS',
2181 'F': 'OS_FREEBSD',
2182 'L': 'OS_LINUX',
2183 'M': 'OS_MACOSX',
2184 'N': 'OS_NACL',
2185 'O': 'OS_OPENBSD',
2186 'P': 'OS_POSIX',
2187 'S': 'OS_SOLARIS',
2188 'W': 'OS_WIN'}[bad_macro[3].upper()]
2189 except KeyError:
2190 return ''
2191
2192
2193def _CheckForInvalidOSMacrosInFile(input_api, f):
2194 """Check for sensible looking, totally invalid OS macros."""
2195 preprocessor_statement = input_api.re.compile(r'^\s*#')
2196 os_macro = input_api.re.compile(r'defined\((OS_[^)]+)\)')
2197 results = []
2198 for lnum, line in f.ChangedContents():
2199 if preprocessor_statement.search(line):
2200 for match in os_macro.finditer(line):
2201 if not match.group(1) in _VALID_OS_MACROS:
2202 good = _DidYouMeanOSMacro(match.group(1))
2203 did_you_mean = ' (did you mean %s?)' % good if good else ''
2204 results.append(' %s:%d %s%s' % (f.LocalPath(),
2205 lnum,
2206 match.group(1),
2207 did_you_mean))
2208 return results
2209
2210
2211def _CheckForInvalidOSMacros(input_api, output_api):
2212 """Check all affected files for invalid OS macros."""
2213 bad_macros = []
2214 for f in input_api.AffectedFiles():
ellyjones47654342016-05-06 15:50:472215 if not f.LocalPath().endswith(('.py', '.js', '.html', '.css', '.md')):
[email protected]b00342e7f2013-03-26 16:21:542216 bad_macros.extend(_CheckForInvalidOSMacrosInFile(input_api, f))
2217
2218 if not bad_macros:
2219 return []
2220
2221 return [output_api.PresubmitError(
2222 'Possibly invalid OS macro[s] found. Please fix your code\n'
2223 'or add your macro to src/PRESUBMIT.py.', bad_macros)]
2224
lliabraa35bab3932014-10-01 12:16:442225
2226def _CheckForInvalidIfDefinedMacrosInFile(input_api, f):
2227 """Check all affected files for invalid "if defined" macros."""
2228 ALWAYS_DEFINED_MACROS = (
2229 "TARGET_CPU_PPC",
2230 "TARGET_CPU_PPC64",
2231 "TARGET_CPU_68K",
2232 "TARGET_CPU_X86",
2233 "TARGET_CPU_ARM",
2234 "TARGET_CPU_MIPS",
2235 "TARGET_CPU_SPARC",
2236 "TARGET_CPU_ALPHA",
2237 "TARGET_IPHONE_SIMULATOR",
2238 "TARGET_OS_EMBEDDED",
2239 "TARGET_OS_IPHONE",
2240 "TARGET_OS_MAC",
2241 "TARGET_OS_UNIX",
2242 "TARGET_OS_WIN32",
2243 )
2244 ifdef_macro = input_api.re.compile(r'^\s*#.*(?:ifdef\s|defined\()([^\s\)]+)')
2245 results = []
2246 for lnum, line in f.ChangedContents():
2247 for match in ifdef_macro.finditer(line):
2248 if match.group(1) in ALWAYS_DEFINED_MACROS:
2249 always_defined = ' %s is always defined. ' % match.group(1)
2250 did_you_mean = 'Did you mean \'#if %s\'?' % match.group(1)
2251 results.append(' %s:%d %s\n\t%s' % (f.LocalPath(),
2252 lnum,
2253 always_defined,
2254 did_you_mean))
2255 return results
2256
2257
2258def _CheckForInvalidIfDefinedMacros(input_api, output_api):
2259 """Check all affected files for invalid "if defined" macros."""
2260 bad_macros = []
2261 for f in input_api.AffectedFiles():
2262 if f.LocalPath().endswith(('.h', '.c', '.cc', '.m', '.mm')):
2263 bad_macros.extend(_CheckForInvalidIfDefinedMacrosInFile(input_api, f))
2264
2265 if not bad_macros:
2266 return []
2267
2268 return [output_api.PresubmitError(
2269 'Found ifdef check on always-defined macro[s]. Please fix your code\n'
2270 'or check the list of ALWAYS_DEFINED_MACROS in src/PRESUBMIT.py.',
2271 bad_macros)]
2272
2273
mlamouria82272622014-09-16 18:45:042274def _CheckForIPCRules(input_api, output_api):
2275 """Check for same IPC rules described in
2276 http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc
2277 """
2278 base_pattern = r'IPC_ENUM_TRAITS\('
2279 inclusion_pattern = input_api.re.compile(r'(%s)' % base_pattern)
2280 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_pattern)
2281
2282 problems = []
2283 for f in input_api.AffectedSourceFiles(None):
2284 local_path = f.LocalPath()
2285 if not local_path.endswith('.h'):
2286 continue
2287 for line_number, line in f.ChangedContents():
2288 if inclusion_pattern.search(line) and not comment_pattern.search(line):
2289 problems.append(
2290 '%s:%d\n %s' % (local_path, line_number, line.strip()))
2291
2292 if problems:
2293 return [output_api.PresubmitPromptWarning(
2294 _IPC_ENUM_TRAITS_DEPRECATED, problems)]
2295 else:
2296 return []
2297
[email protected]b00342e7f2013-03-26 16:21:542298
mostynbb639aca52015-01-07 20:31:232299def _CheckForWindowsLineEndings(input_api, output_api):
2300 """Check source code and known ascii text files for Windows style line
2301 endings.
2302 """
earthdok1b5e0ee2015-03-10 15:19:102303 known_text_files = r'.*\.(txt|html|htm|mhtml|py|gyp|gypi|gn|isolate)$'
mostynbb639aca52015-01-07 20:31:232304
2305 file_inclusion_pattern = (
2306 known_text_files,
2307 r'.+%s' % _IMPLEMENTATION_EXTENSIONS
2308 )
2309
2310 filter = lambda f: input_api.FilterSourceFile(
2311 f, white_list=file_inclusion_pattern, black_list=None)
2312 files = [f.LocalPath() for f in
2313 input_api.AffectedSourceFiles(filter)]
2314
2315 problems = []
2316
2317 for file in files:
2318 fp = open(file, 'r')
2319 for line in fp:
2320 if line.endswith('\r\n'):
2321 problems.append(file)
2322 break
2323 fp.close()
2324
2325 if problems:
2326 return [output_api.PresubmitPromptWarning('Are you sure that you want '
2327 'these files to contain Windows style line endings?\n' +
2328 '\n'.join(problems))]
2329
2330 return []
2331
2332
pastarmovj89f7ee12016-09-20 14:58:132333def _CheckSyslogUseWarning(input_api, output_api, source_file_filter=None,
2334 lint_filters=None, verbose_level=None):
2335 """Checks that all source files use SYSLOG properly."""
2336 syslog_files = []
2337 for f in input_api.AffectedSourceFiles(source_file_filter):
pastarmovj032ba5bc2017-01-12 10:41:562338 for line_number, line in f.ChangedContents():
2339 if 'SYSLOG' in line:
2340 syslog_files.append(f.LocalPath() + ':' + str(line_number))
2341
pastarmovj89f7ee12016-09-20 14:58:132342 if syslog_files:
2343 return [output_api.PresubmitPromptWarning(
2344 'Please make sure there are no privacy sensitive bits of data in SYSLOG'
2345 ' calls.\nFiles to check:\n', items=syslog_files)]
2346 return []
2347
2348
[email protected]1f7b4172010-01-28 01:17:342349def CheckChangeOnUpload(input_api, output_api):
2350 results = []
2351 results.extend(_CommonChecks(input_api, output_api))
tandriief664692014-09-23 14:51:472352 results.extend(_CheckValidHostsInDEPS(input_api, output_api))
scottmg39b29952014-12-08 18:31:282353 results.extend(
jam93a6ee792017-02-08 23:59:222354 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
mcasasb7440c282015-02-04 14:52:192355 results.extend(_CheckUmaHistogramChanges(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:222356 results.extend(_AndroidSpecificOnUploadChecks(input_api, output_api))
pastarmovj89f7ee12016-09-20 14:58:132357 results.extend(_CheckSyslogUseWarning(input_api, output_api))
estadee17314a02017-01-12 16:22:162358 results.extend(_CheckGoogleSupportAnswerUrl(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542359 return results
[email protected]ca8d19842009-02-19 16:33:122360
2361
[email protected]1bfb8322014-04-23 01:02:412362def GetTryServerMasterForBot(bot):
2363 """Returns the Try Server master for the given bot.
2364
[email protected]0bb112362014-07-26 04:38:322365 It tries to guess the master from the bot name, but may still fail
2366 and return None. There is no longer a default master.
2367 """
2368 # Potentially ambiguous bot names are listed explicitly.
2369 master_map = {
tandriie5587792016-07-14 00:34:502370 'chromium_presubmit': 'master.tryserver.chromium.linux',
2371 'tools_build_presubmit': 'master.tryserver.chromium.linux',
[email protected]1bfb8322014-04-23 01:02:412372 }
[email protected]0bb112362014-07-26 04:38:322373 master = master_map.get(bot)
2374 if not master:
wnwen4fbaab82016-05-25 12:54:362375 if 'android' in bot:
tandriie5587792016-07-14 00:34:502376 master = 'master.tryserver.chromium.android'
wnwen4fbaab82016-05-25 12:54:362377 elif 'linux' in bot or 'presubmit' in bot:
tandriie5587792016-07-14 00:34:502378 master = 'master.tryserver.chromium.linux'
[email protected]0bb112362014-07-26 04:38:322379 elif 'win' in bot:
tandriie5587792016-07-14 00:34:502380 master = 'master.tryserver.chromium.win'
[email protected]0bb112362014-07-26 04:38:322381 elif 'mac' in bot or 'ios' in bot:
tandriie5587792016-07-14 00:34:502382 master = 'master.tryserver.chromium.mac'
[email protected]0bb112362014-07-26 04:38:322383 return master
[email protected]1bfb8322014-04-23 01:02:412384
2385
Paweł Hajdan, Jr55083782014-12-19 20:32:562386def GetDefaultTryConfigs(bots):
2387 """Returns a list of ('bot', set(['tests']), filtered by [bots].
[email protected]38c6a512013-12-18 23:48:012388 """
2389
Paweł Hajdan, Jr55083782014-12-19 20:32:562390 builders_and_tests = dict((bot, set(['defaulttests'])) for bot in bots)
[email protected]1bfb8322014-04-23 01:02:412391
2392 # Build up the mapping from tryserver master to bot/test.
2393 out = dict()
Paweł Hajdan, Jr55083782014-12-19 20:32:562394 for bot, tests in builders_and_tests.iteritems():
[email protected]1bfb8322014-04-23 01:02:412395 out.setdefault(GetTryServerMasterForBot(bot), {})[bot] = tests
2396 return out
[email protected]38c6a512013-12-18 23:48:012397
2398
[email protected]ca8d19842009-02-19 16:33:122399def CheckChangeOnCommit(input_api, output_api):
[email protected]fe5f57c52009-06-05 14:25:542400 results = []
[email protected]1f7b4172010-01-28 01:17:342401 results.extend(_CommonChecks(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542402 # Make sure the tree is 'open'.
[email protected]806e98e2010-03-19 17:49:272403 results.extend(input_api.canned_checks.CheckTreeIsOpen(
[email protected]7f238152009-08-12 19:00:342404 input_api,
2405 output_api,
[email protected]2fdd1f362013-01-16 03:56:032406 json_url='http://chromium-status.appspot.com/current?format=json'))
[email protected]806e98e2010-03-19 17:49:272407
jam93a6ee792017-02-08 23:59:222408 results.extend(
2409 input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
[email protected]3e4eb112011-01-18 03:29:542410 results.extend(input_api.canned_checks.CheckChangeHasBugField(
2411 input_api, output_api))
[email protected]c4b47562011-12-05 23:39:412412 results.extend(input_api.canned_checks.CheckChangeHasDescription(
2413 input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542414 return results