blob: 861990ec8f339db39782df0d25d135abc5f8a416 [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$",
[email protected]4306417642009-06-11 00:33:4028)
[email protected]ca8d19842009-02-19 16:33:1229
wnwenbdc444e2016-05-25 13:44:1530
jochen9ea8fdbc2014-09-25 13:21:3531# The NetscapePlugIn library is excluded from pan-project as it will soon
32# be deleted together with the rest of the NPAPI and it's not worthwhile to
33# update the coding style until then.
[email protected]3de922f2013-12-20 13:27:3834_TESTRUNNER_PATHS = (
[email protected]de28fed2e2014-02-01 14:36:3235 r"^content[\\\/]shell[\\\/]tools[\\\/]plugin[\\\/].*",
[email protected]3de922f2013-12-20 13:27:3836)
37
wnwenbdc444e2016-05-25 13:44:1538
[email protected]06e6d0ff2012-12-11 01:36:4439# Fragment of a regular expression that matches C++ and Objective-C++
40# implementation files.
41_IMPLEMENTATION_EXTENSIONS = r'\.(cc|cpp|cxx|mm)$'
42
wnwenbdc444e2016-05-25 13:44:1543
[email protected]06e6d0ff2012-12-11 01:36:4444# Regular expression that matches code only used for test binaries
45# (best effort).
46_TEST_CODE_EXCLUDED_PATHS = (
joaodasilva718f87672014-08-30 09:25:4947 r'.*[\\\/](fake_|test_|mock_).+%s' % _IMPLEMENTATION_EXTENSIONS,
[email protected]06e6d0ff2012-12-11 01:36:4448 r'.+_test_(base|support|util)%s' % _IMPLEMENTATION_EXTENSIONS,
[email protected]6e04f8c2014-01-29 18:08:3249 r'.+_(api|browser|kif|perf|pixel|unit|ui)?test(_[a-z]+)?%s' %
[email protected]e2d7e6f2013-04-23 12:57:1250 _IMPLEMENTATION_EXTENSIONS,
[email protected]06e6d0ff2012-12-11 01:36:4451 r'.+profile_sync_service_harness%s' % _IMPLEMENTATION_EXTENSIONS,
joaodasilva718f87672014-08-30 09:25:4952 r'.*[\\\/](test|tool(s)?)[\\\/].*',
[email protected]ef070cc2013-05-03 11:53:0553 # content_shell is used for running layout tests.
joaodasilva718f87672014-08-30 09:25:4954 r'content[\\\/]shell[\\\/].*',
[email protected]7b054982013-11-27 00:44:4755 # Non-production example code.
joaodasilva718f87672014-08-30 09:25:4956 r'mojo[\\\/]examples[\\\/].*',
[email protected]8176de12014-06-20 19:07:0857 # Launcher for running iOS tests on the simulator.
joaodasilva718f87672014-08-30 09:25:4958 r'testing[\\\/]iossim[\\\/]iossim\.mm$',
[email protected]06e6d0ff2012-12-11 01:36:4459)
[email protected]ca8d19842009-02-19 16:33:1260
wnwenbdc444e2016-05-25 13:44:1561
[email protected]eea609a2011-11-18 13:10:1262_TEST_ONLY_WARNING = (
63 'You might be calling functions intended only for testing from\n'
64 'production code. It is OK to ignore this warning if you know what\n'
65 'you are doing, as the heuristics used to detect the situation are\n'
[email protected]b0149772014-03-27 16:47:5866 'not perfect. The commit queue will not block on this warning.')
[email protected]eea609a2011-11-18 13:10:1267
68
[email protected]cf9b78f2012-11-14 11:40:2869_INCLUDE_ORDER_WARNING = (
marjaa017dc482015-03-09 17:13:4070 'Your #include order seems to be broken. Remember to use the right '
avice9a8982015-11-24 20:36:2171 'collation (LC_COLLATE=C) and check\nhttps://google.github.io/styleguide/'
72 'cppguide.html#Names_and_Order_of_Includes')
[email protected]cf9b78f2012-11-14 11:40:2873
wnwenbdc444e2016-05-25 13:44:1574
[email protected]127f18ec2012-06-16 05:05:5975_BANNED_OBJC_FUNCTIONS = (
76 (
77 'addTrackingRect:',
[email protected]23e6cbc2012-06-16 18:51:2078 (
79 'The use of -[NSView addTrackingRect:owner:userData:assumeInside:] is'
[email protected]127f18ec2012-06-16 05:05:5980 'prohibited. Please use CrTrackingArea instead.',
81 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
82 ),
83 False,
84 ),
85 (
[email protected]eaae1972014-04-16 04:17:2686 r'/NSTrackingArea\W',
[email protected]23e6cbc2012-06-16 18:51:2087 (
88 'The use of NSTrackingAreas is prohibited. Please use CrTrackingArea',
[email protected]127f18ec2012-06-16 05:05:5989 'instead.',
90 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
91 ),
92 False,
93 ),
94 (
95 'convertPointFromBase:',
[email protected]23e6cbc2012-06-16 18:51:2096 (
97 'The use of -[NSView convertPointFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:5998 'Please use |convertPoint:(point) fromView:nil| instead.',
99 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
100 ),
101 True,
102 ),
103 (
104 'convertPointToBase:',
[email protected]23e6cbc2012-06-16 18:51:20105 (
106 'The use of -[NSView convertPointToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59107 'Please use |convertPoint:(point) toView:nil| instead.',
108 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
109 ),
110 True,
111 ),
112 (
113 'convertRectFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20114 (
115 'The use of -[NSView convertRectFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59116 'Please use |convertRect:(point) fromView:nil| instead.',
117 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
118 ),
119 True,
120 ),
121 (
122 'convertRectToBase:',
[email protected]23e6cbc2012-06-16 18:51:20123 (
124 'The use of -[NSView convertRectToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59125 'Please use |convertRect:(point) toView:nil| instead.',
126 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
127 ),
128 True,
129 ),
130 (
131 'convertSizeFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20132 (
133 'The use of -[NSView convertSizeFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59134 'Please use |convertSize:(point) fromView:nil| instead.',
135 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
136 ),
137 True,
138 ),
139 (
140 'convertSizeToBase:',
[email protected]23e6cbc2012-06-16 18:51:20141 (
142 'The use of -[NSView convertSizeToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59143 'Please use |convertSize:(point) toView:nil| instead.',
144 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
145 ),
146 True,
147 ),
jif65398702016-10-27 10:19:48148 (
149 r"/\s+UTF8String\s*]",
150 (
151 'The use of -[NSString UTF8String] is dangerous as it can return null',
152 'even if |canBeConvertedToEncoding:NSUTF8StringEncoding| returns YES.',
153 'Please use |SysNSStringToUTF8| instead.',
154 ),
155 True,
156 ),
[email protected]127f18ec2012-06-16 05:05:59157)
158
159
160_BANNED_CPP_FUNCTIONS = (
[email protected]23e6cbc2012-06-16 18:51:20161 # Make sure that gtest's FRIEND_TEST() macro is not used; the
162 # FRIEND_TEST_ALL_PREFIXES() macro from base/gtest_prod_util.h should be
[email protected]e00ccc92012-11-01 17:32:30163 # used instead since that allows for FLAKY_ and DISABLED_ prefixes.
[email protected]23e6cbc2012-06-16 18:51:20164 (
165 'FRIEND_TEST(',
166 (
[email protected]e3c945502012-06-26 20:01:49167 'Chromium code should not use gtest\'s FRIEND_TEST() macro. Include',
[email protected]23e6cbc2012-06-16 18:51:20168 'base/gtest_prod_util.h and use FRIEND_TEST_ALL_PREFIXES() instead.',
169 ),
170 False,
[email protected]7345da02012-11-27 14:31:49171 (),
[email protected]23e6cbc2012-06-16 18:51:20172 ),
173 (
thomasanderson4b569052016-09-14 20:15:53174 r'XSelectInput|CWEventMask|XCB_CW_EVENT_MASK',
175 (
176 'Chrome clients wishing to select events on X windows should use',
177 'ui::XScopedEventSelector. It is safe to ignore this warning only if',
178 'you are selecting events from the GPU process, or if you are using',
179 'an XDisplay other than gfx::GetXDisplay().',
180 ),
181 True,
182 (
183 r"^ui[\\\/]gl[\\\/].*\.cc$",
184 r"^media[\\\/]gpu[\\\/].*\.cc$",
185 r"^gpu[\\\/].*\.cc$",
186 ),
187 ),
188 (
[email protected]23e6cbc2012-06-16 18:51:20189 'ScopedAllowIO',
190 (
[email protected]e3c945502012-06-26 20:01:49191 'New code should not use ScopedAllowIO. Post a task to the blocking',
192 'pool or the FILE thread instead.',
[email protected]23e6cbc2012-06-16 18:51:20193 ),
[email protected]e3c945502012-06-26 20:01:49194 True,
[email protected]7345da02012-11-27 14:31:49195 (
nyad2c548b2015-12-09 03:22:32196 r"^base[\\\/]process[\\\/]process_linux\.cc$",
thestig75844fdb2014-09-09 19:47:10197 r"^base[\\\/]process[\\\/]process_metrics_linux\.cc$",
kmarshallbb619532016-01-29 21:24:49198 r"^blimp[\\\/]engine[\\\/]app[\\\/]blimp_browser_main_parts\.cc$",
tfarina0923ac52015-01-07 03:21:22199 r"^chrome[\\\/]browser[\\\/]chromeos[\\\/]boot_times_recorder\.cc$",
sky0e07a142016-03-25 21:27:31200 r"^chrome[\\\/]browser[\\\/]lifetime[\\\/]application_lifetime\.cc$",
alematee4016bb2014-11-12 17:38:51201 r"^chrome[\\\/]browser[\\\/]chromeos[\\\/]"
202 "customization_document_browsertest\.cc$",
philipj3f9d5bde2014-08-28 14:09:09203 r"^components[\\\/]crash[\\\/]app[\\\/]breakpad_mac\.mm$",
jochene9ba6dd2016-02-23 17:20:49204 r"^content[\\\/]shell[\\\/]browser[\\\/]layout_test[\\\/]" +
205 r"test_info_extractor\.cc$",
lukasza7947ccd2016-07-28 21:56:25206 r"^content[\\\/].*browser(|_)test[a-zA-Z_]*\.cc$",
[email protected]de7d61ff2013-08-20 11:30:41207 r"^content[\\\/]shell[\\\/]browser[\\\/]shell_browser_main\.cc$",
208 r"^content[\\\/]shell[\\\/]browser[\\\/]shell_message_filter\.cc$",
lukasza7947ccd2016-07-28 21:56:25209 r"^content[\\\/]test[\\\/]ppapi[\\\/]ppapi_test\.cc$",
jamesra03ae492014-10-03 04:26:48210 r"^mojo[\\\/]edk[\\\/]embedder[\\\/]" +
211 r"simple_platform_shared_buffer_posix\.cc$",
[email protected]398ad132013-04-02 15:11:01212 r"^net[\\\/]disk_cache[\\\/]cache_util\.cc$",
lukasza7947ccd2016-07-28 21:56:25213 r"^net[\\\/]cert[\\\/]test_root_certs\.cc$",
214 r"^net[\\\/]test[\\\/]embedded_test_server[\\\/]" +
215 r"embedded_test_server\.cc$",
216 r"^net[\\\/]test[\\\/]spawned_test_server[\\\/]local_test_server\.cc$",
217 r"^net[\\\/]test[\\\/]test_data_directory\.cc$",
[email protected]1f52a572014-05-12 23:21:54218 r"^net[\\\/]url_request[\\\/]test_url_fetcher_factory\.cc$",
sergeyu2c41f9842016-12-10 01:45:16219 r"^remoting[\\\/]protocol[\\\/]webrtc_transport\.cc$",
lambroslambrouf6fb94ea2016-06-27 21:21:53220 r"^ui[\\\/]base[\\\/]material_design[\\\/]"
221 "material_design_controller\.cc$",
kylechar16666242016-07-04 20:54:45222 r"^ui[\\\/]gl[\\\/]init[\\\/]gl_initializer_mac\.cc$",
223 r"^ui[\\\/]gl[\\\/]init[\\\/]gl_initializer_win\.cc$",
224 r"^ui[\\\/]gl[\\\/]init[\\\/]gl_initializer_x11\.cc$",
225 r"^ui[\\\/]ozone[\\\/]platform[\\\/]drm[\\\/]host[\\\/]"
226 "drm_display_host_manager\.cc$",
[email protected]7345da02012-11-27 14:31:49227 ),
[email protected]23e6cbc2012-06-16 18:51:20228 ),
[email protected]52657f62013-05-20 05:30:31229 (
tomhudsone2c14d552016-05-26 17:07:46230 'setMatrixClip',
231 (
232 'Overriding setMatrixClip() is prohibited; ',
233 'the base function is deprecated. ',
234 ),
235 True,
236 (),
237 ),
238 (
[email protected]52657f62013-05-20 05:30:31239 'SkRefPtr',
240 (
241 'The use of SkRefPtr is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22242 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31243 ),
244 True,
245 (),
246 ),
247 (
248 'SkAutoRef',
249 (
250 'The indirect use of SkRefPtr via SkAutoRef is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22251 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31252 ),
253 True,
254 (),
255 ),
256 (
257 'SkAutoTUnref',
258 (
259 'The use of SkAutoTUnref is dangerous because it implicitly ',
tomhudson7e6e0512016-04-19 19:27:22260 'converts to a raw pointer. Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31261 ),
262 True,
263 (),
264 ),
265 (
266 'SkAutoUnref',
267 (
268 'The indirect use of SkAutoTUnref through SkAutoUnref is dangerous ',
269 'because it implicitly converts to a raw pointer. ',
tomhudson7e6e0512016-04-19 19:27:22270 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31271 ),
272 True,
273 (),
274 ),
[email protected]d89eec82013-12-03 14:10:59275 (
276 r'/HANDLE_EINTR\(.*close',
277 (
278 'HANDLE_EINTR(close) is invalid. If close fails with EINTR, the file',
279 'descriptor will be closed, and it is incorrect to retry the close.',
280 'Either call close directly and ignore its return value, or wrap close',
281 'in IGNORE_EINTR to use its return value. See http://crbug.com/269623'
282 ),
283 True,
284 (),
285 ),
286 (
287 r'/IGNORE_EINTR\((?!.*close)',
288 (
289 'IGNORE_EINTR is only valid when wrapping close. To wrap other system',
290 'calls, use HANDLE_EINTR. See http://crbug.com/269623',
291 ),
292 True,
293 (
294 # Files that #define IGNORE_EINTR.
295 r'^base[\\\/]posix[\\\/]eintr_wrapper\.h$',
296 r'^ppapi[\\\/]tests[\\\/]test_broker\.cc$',
297 ),
298 ),
[email protected]ec5b3f02014-04-04 18:43:43299 (
300 r'/v8::Extension\(',
301 (
302 'Do not introduce new v8::Extensions into the code base, use',
303 'gin::Wrappable instead. See http://crbug.com/334679',
304 ),
305 True,
[email protected]f55c90ee62014-04-12 00:50:03306 (
joaodasilva718f87672014-08-30 09:25:49307 r'extensions[\\\/]renderer[\\\/]safe_builtins\.*',
[email protected]f55c90ee62014-04-12 00:50:03308 ),
[email protected]ec5b3f02014-04-04 18:43:43309 ),
skyostilf9469f72015-04-20 10:38:52310 (
jame2d1a952016-04-02 00:27:10311 '#pragma comment(lib,',
312 (
313 'Specify libraries to link with in build files and not in the source.',
314 ),
315 True,
316 (),
317 ),
dcheng8f0694bae2016-10-12 15:58:15318 (
avid5a337982016-10-19 23:07:15319 r'STLDeleteElements', # http://crbug.com/555865
320 (
321 'This call is obsolete with C++ 11; create a container with owning',
322 'pointers instead (e.g. std::vector<std::unique_ptr<x>> ).',
323 ),
324 True,
325 (),
326 ),
327 (
328 r'STLDeleteValues', # http://crbug.com/555865
329 (
330 'This call is obsolete with C++ 11; create a map with owning',
331 'pointers instead (e.g. std::map<std::string, std::unique_ptr<x>> ).',
332 ),
333 True,
334 (),
335 ),
[email protected]127f18ec2012-06-16 05:05:59336)
337
wnwenbdc444e2016-05-25 13:44:15338
mlamouria82272622014-09-16 18:45:04339_IPC_ENUM_TRAITS_DEPRECATED = (
340 'You are using IPC_ENUM_TRAITS() in your code. It has been deprecated.\n'
341 'See http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc')
342
[email protected]127f18ec2012-06-16 05:05:59343
[email protected]b00342e7f2013-03-26 16:21:54344_VALID_OS_MACROS = (
345 # Please keep sorted.
346 'OS_ANDROID',
347 'OS_BSD',
348 'OS_CAT', # For testing.
349 'OS_CHROMEOS',
350 'OS_FREEBSD',
351 'OS_IOS',
352 'OS_LINUX',
353 'OS_MACOSX',
354 'OS_NACL',
hidehikof7295f22014-10-28 11:57:21355 'OS_NACL_NONSFI',
356 'OS_NACL_SFI',
krytarowski969759f2016-07-31 23:55:12357 'OS_NETBSD',
[email protected]b00342e7f2013-03-26 16:21:54358 'OS_OPENBSD',
359 'OS_POSIX',
[email protected]eda7afa12014-02-06 12:27:37360 'OS_QNX',
[email protected]b00342e7f2013-03-26 16:21:54361 'OS_SOLARIS',
[email protected]b00342e7f2013-03-26 16:21:54362 'OS_WIN',
363)
364
365
agrievef32bcc72016-04-04 14:57:40366_ANDROID_SPECIFIC_PYDEPS_FILES = [
367 'build/android/test_runner.pydeps',
agrieve732db3a2016-04-26 19:18:19368 'net/tools/testserver/testserver.pydeps',
agrievef32bcc72016-04-04 14:57:40369]
370
wnwenbdc444e2016-05-25 13:44:15371
agrievef32bcc72016-04-04 14:57:40372_GENERIC_PYDEPS_FILES = [
agrievef32bcc72016-04-04 14:57:40373]
374
wnwenbdc444e2016-05-25 13:44:15375
agrievef32bcc72016-04-04 14:57:40376_ALL_PYDEPS_FILES = _ANDROID_SPECIFIC_PYDEPS_FILES + _GENERIC_PYDEPS_FILES
377
378
[email protected]55459852011-08-10 15:17:19379def _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api):
380 """Attempts to prevent use of functions intended only for testing in
381 non-testing code. For now this is just a best-effort implementation
382 that ignores header files and may have some false positives. A
383 better implementation would probably need a proper C++ parser.
384 """
385 # We only scan .cc files and the like, as the declaration of
386 # for-testing functions in header files are hard to distinguish from
387 # calls to such functions without a proper C++ parser.
[email protected]06e6d0ff2012-12-11 01:36:44388 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
[email protected]55459852011-08-10 15:17:19389
jochenc0d4808c2015-07-27 09:25:42390 base_function_pattern = r'[ :]test::[^\s]+|ForTest(s|ing)?|for_test(s|ing)?'
[email protected]55459852011-08-10 15:17:19391 inclusion_pattern = input_api.re.compile(r'(%s)\s*\(' % base_function_pattern)
[email protected]23501822014-05-14 02:06:09392 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_function_pattern)
[email protected]55459852011-08-10 15:17:19393 exclusion_pattern = input_api.re.compile(
394 r'::[A-Za-z0-9_]+(%s)|(%s)[^;]+\{' % (
395 base_function_pattern, base_function_pattern))
396
397 def FilterFile(affected_file):
[email protected]06e6d0ff2012-12-11 01:36:44398 black_list = (_EXCLUDED_PATHS +
399 _TEST_CODE_EXCLUDED_PATHS +
400 input_api.DEFAULT_BLACK_LIST)
[email protected]55459852011-08-10 15:17:19401 return input_api.FilterSourceFile(
402 affected_file,
403 white_list=(file_inclusion_pattern, ),
404 black_list=black_list)
405
406 problems = []
407 for f in input_api.AffectedSourceFiles(FilterFile):
408 local_path = f.LocalPath()
[email protected]825d27182014-01-02 21:24:24409 for line_number, line in f.ChangedContents():
[email protected]2fdd1f362013-01-16 03:56:03410 if (inclusion_pattern.search(line) and
[email protected]de4f7d22013-05-23 14:27:46411 not comment_pattern.search(line) and
[email protected]2fdd1f362013-01-16 03:56:03412 not exclusion_pattern.search(line)):
[email protected]55459852011-08-10 15:17:19413 problems.append(
[email protected]2fdd1f362013-01-16 03:56:03414 '%s:%d\n %s' % (local_path, line_number, line.strip()))
[email protected]55459852011-08-10 15:17:19415
416 if problems:
[email protected]f7051d52013-04-02 18:31:42417 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
[email protected]2fdd1f362013-01-16 03:56:03418 else:
419 return []
[email protected]55459852011-08-10 15:17:19420
421
[email protected]10689ca2011-09-02 02:31:54422def _CheckNoIOStreamInHeaders(input_api, output_api):
423 """Checks to make sure no .h files include <iostream>."""
424 files = []
425 pattern = input_api.re.compile(r'^#include\s*<iostream>',
426 input_api.re.MULTILINE)
427 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
428 if not f.LocalPath().endswith('.h'):
429 continue
430 contents = input_api.ReadFile(f)
431 if pattern.search(contents):
432 files.append(f)
433
434 if len(files):
yolandyandaabc6d2016-04-18 18:29:39435 return [output_api.PresubmitError(
[email protected]6c063c62012-07-11 19:11:06436 'Do not #include <iostream> in header files, since it inserts static '
437 'initialization into every file including the header. Instead, '
[email protected]10689ca2011-09-02 02:31:54438 '#include <ostream>. See http://crbug.com/94794',
439 files) ]
440 return []
441
442
[email protected]72df4e782012-06-21 16:28:18443def _CheckNoUNIT_TESTInSourceFiles(input_api, output_api):
danakj61c1aa22015-10-26 19:55:52444 """Checks to make sure no source files use UNIT_TEST."""
[email protected]72df4e782012-06-21 16:28:18445 problems = []
446 for f in input_api.AffectedFiles():
447 if (not f.LocalPath().endswith(('.cc', '.mm'))):
448 continue
449
450 for line_num, line in f.ChangedContents():
[email protected]549f86a2013-11-19 13:00:04451 if 'UNIT_TEST ' in line or line.endswith('UNIT_TEST'):
[email protected]72df4e782012-06-21 16:28:18452 problems.append(' %s:%d' % (f.LocalPath(), line_num))
453
454 if not problems:
455 return []
456 return [output_api.PresubmitPromptWarning('UNIT_TEST is only for headers.\n' +
457 '\n'.join(problems))]
458
459
danakj61c1aa22015-10-26 19:55:52460def _CheckDCHECK_IS_ONHasBraces(input_api, output_api):
461 """Checks to make sure DCHECK_IS_ON() does not skip the braces."""
462 errors = []
463 pattern = input_api.re.compile(r'DCHECK_IS_ON(?!\(\))',
464 input_api.re.MULTILINE)
465 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
466 if (not f.LocalPath().endswith(('.cc', '.mm', '.h'))):
467 continue
468 for lnum, line in f.ChangedContents():
469 if input_api.re.search(pattern, line):
dchenge07de812016-06-20 19:27:17470 errors.append(output_api.PresubmitError(
471 ('%s:%d: Use of DCHECK_IS_ON() must be written as "#if ' +
472 'DCHECK_IS_ON()", not forgetting the braces.')
473 % (f.LocalPath(), lnum)))
danakj61c1aa22015-10-26 19:55:52474 return errors
475
476
mcasasb7440c282015-02-04 14:52:19477def _FindHistogramNameInLine(histogram_name, line):
478 """Tries to find a histogram name or prefix in a line."""
479 if not "affected-histogram" in line:
480 return histogram_name in line
481 # A histogram_suffixes tag type has an affected-histogram name as a prefix of
482 # the histogram_name.
483 if not '"' in line:
484 return False
485 histogram_prefix = line.split('\"')[1]
486 return histogram_prefix in histogram_name
487
488
489def _CheckUmaHistogramChanges(input_api, output_api):
490 """Check that UMA histogram names in touched lines can still be found in other
491 lines of the patch or in histograms.xml. Note that this check would not catch
492 the reverse: changes in histograms.xml not matched in the code itself."""
493 touched_histograms = []
494 histograms_xml_modifications = []
495 pattern = input_api.re.compile('UMA_HISTOGRAM.*\("(.*)"')
496 for f in input_api.AffectedFiles():
497 # If histograms.xml itself is modified, keep the modified lines for later.
498 if f.LocalPath().endswith(('histograms.xml')):
499 histograms_xml_modifications = f.ChangedContents()
500 continue
501 if not f.LocalPath().endswith(('cc', 'mm', 'cpp')):
502 continue
503 for line_num, line in f.ChangedContents():
504 found = pattern.search(line)
505 if found:
506 touched_histograms.append([found.group(1), f, line_num])
507
508 # Search for the touched histogram names in the local modifications to
509 # histograms.xml, and, if not found, on the base histograms.xml file.
510 unmatched_histograms = []
511 for histogram_info in touched_histograms:
512 histogram_name_found = False
513 for line_num, line in histograms_xml_modifications:
514 histogram_name_found = _FindHistogramNameInLine(histogram_info[0], line)
515 if histogram_name_found:
516 break
517 if not histogram_name_found:
518 unmatched_histograms.append(histogram_info)
519
eromanb90c82e7e32015-04-01 15:13:49520 histograms_xml_path = 'tools/metrics/histograms/histograms.xml'
mcasasb7440c282015-02-04 14:52:19521 problems = []
522 if unmatched_histograms:
eromanb90c82e7e32015-04-01 15:13:49523 with open(histograms_xml_path) as histograms_xml:
mcasasb7440c282015-02-04 14:52:19524 for histogram_name, f, line_num in unmatched_histograms:
mcasas39c1b8b2015-02-25 15:33:45525 histograms_xml.seek(0)
mcasasb7440c282015-02-04 14:52:19526 histogram_name_found = False
527 for line in histograms_xml:
528 histogram_name_found = _FindHistogramNameInLine(histogram_name, line)
529 if histogram_name_found:
530 break
531 if not histogram_name_found:
532 problems.append(' [%s:%d] %s' %
533 (f.LocalPath(), line_num, histogram_name))
534
535 if not problems:
536 return []
537 return [output_api.PresubmitPromptWarning('Some UMA_HISTOGRAM lines have '
538 'been modified and the associated histogram name has no match in either '
eromanb90c82e7e32015-04-01 15:13:49539 '%s or the modifications of it:' % (histograms_xml_path), problems)]
mcasasb7440c282015-02-04 14:52:19540
wnwenbdc444e2016-05-25 13:44:15541
yolandyandaabc6d2016-04-18 18:29:39542def _CheckFlakyTestUsage(input_api, output_api):
543 """Check that FlakyTest annotation is our own instead of the android one"""
544 pattern = input_api.re.compile(r'import android.test.FlakyTest;')
545 files = []
546 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
547 if f.LocalPath().endswith('Test.java'):
548 if pattern.search(input_api.ReadFile(f)):
549 files.append(f)
550 if len(files):
551 return [output_api.PresubmitError(
552 'Use org.chromium.base.test.util.FlakyTest instead of '
553 'android.test.FlakyTest',
554 files)]
555 return []
mcasasb7440c282015-02-04 14:52:19556
wnwenbdc444e2016-05-25 13:44:15557
[email protected]8ea5d4b2011-09-13 21:49:22558def _CheckNoNewWStrings(input_api, output_api):
559 """Checks to make sure we don't introduce use of wstrings."""
[email protected]55463aa62011-10-12 00:48:27560 problems = []
[email protected]8ea5d4b2011-09-13 21:49:22561 for f in input_api.AffectedFiles():
[email protected]b5c24292011-11-28 14:38:20562 if (not f.LocalPath().endswith(('.cc', '.h')) or
scottmge6f04402014-11-05 01:59:57563 f.LocalPath().endswith(('test.cc', '_win.cc', '_win.h')) or
pennymac84fd6692016-07-13 22:35:34564 '/win/' in f.LocalPath() or
565 'chrome_elf' in f.LocalPath() or
566 'install_static' in f.LocalPath()):
[email protected]b5c24292011-11-28 14:38:20567 continue
[email protected]8ea5d4b2011-09-13 21:49:22568
[email protected]a11dbe9b2012-08-07 01:32:58569 allowWString = False
[email protected]b5c24292011-11-28 14:38:20570 for line_num, line in f.ChangedContents():
[email protected]a11dbe9b2012-08-07 01:32:58571 if 'presubmit: allow wstring' in line:
572 allowWString = True
573 elif not allowWString and 'wstring' in line:
[email protected]55463aa62011-10-12 00:48:27574 problems.append(' %s:%d' % (f.LocalPath(), line_num))
[email protected]a11dbe9b2012-08-07 01:32:58575 allowWString = False
576 else:
577 allowWString = False
[email protected]8ea5d4b2011-09-13 21:49:22578
[email protected]55463aa62011-10-12 00:48:27579 if not problems:
580 return []
581 return [output_api.PresubmitPromptWarning('New code should not use wstrings.'
[email protected]a11dbe9b2012-08-07 01:32:58582 ' If you are calling a cross-platform API that accepts a wstring, '
583 'fix the API.\n' +
[email protected]55463aa62011-10-12 00:48:27584 '\n'.join(problems))]
[email protected]8ea5d4b2011-09-13 21:49:22585
586
[email protected]2a8ac9c2011-10-19 17:20:44587def _CheckNoDEPSGIT(input_api, output_api):
588 """Make sure .DEPS.git is never modified manually."""
589 if any(f.LocalPath().endswith('.DEPS.git') for f in
590 input_api.AffectedFiles()):
591 return [output_api.PresubmitError(
592 'Never commit changes to .DEPS.git. This file is maintained by an\n'
593 'automated system based on what\'s in DEPS and your changes will be\n'
594 'overwritten.\n'
[email protected]cb706912014-06-28 20:46:34595 '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:44596 'for more information')]
597 return []
598
599
tandriief664692014-09-23 14:51:47600def _CheckValidHostsInDEPS(input_api, output_api):
601 """Checks that DEPS file deps are from allowed_hosts."""
602 # Run only if DEPS file has been modified to annoy fewer bystanders.
603 if all(f.LocalPath() != 'DEPS' for f in input_api.AffectedFiles()):
604 return []
605 # Outsource work to gclient verify
606 try:
607 input_api.subprocess.check_output(['gclient', 'verify'])
608 return []
609 except input_api.subprocess.CalledProcessError, error:
610 return [output_api.PresubmitError(
611 'DEPS file must have only git dependencies.',
612 long_text=error.output)]
613
614
[email protected]127f18ec2012-06-16 05:05:59615def _CheckNoBannedFunctions(input_api, output_api):
616 """Make sure that banned functions are not used."""
617 warnings = []
618 errors = []
619
wnwenbdc444e2016-05-25 13:44:15620 def IsBlacklisted(affected_file, blacklist):
621 local_path = affected_file.LocalPath()
622 for item in blacklist:
623 if input_api.re.match(item, local_path):
624 return True
625 return False
626
627 def CheckForMatch(affected_file, line_num, line, func_name, message, error):
628 matched = False
629 if func_name[0:1] == '/':
630 regex = func_name[1:]
631 if input_api.re.search(regex, line):
632 matched = True
633 elif func_name in line:
dchenge07de812016-06-20 19:27:17634 matched = True
wnwenbdc444e2016-05-25 13:44:15635 if matched:
dchenge07de812016-06-20 19:27:17636 problems = warnings
wnwenbdc444e2016-05-25 13:44:15637 if error:
dchenge07de812016-06-20 19:27:17638 problems = errors
wnwenbdc444e2016-05-25 13:44:15639 problems.append(' %s:%d:' % (affected_file.LocalPath(), line_num))
640 for message_line in message:
641 problems.append(' %s' % message_line)
642
[email protected]127f18ec2012-06-16 05:05:59643 file_filter = lambda f: f.LocalPath().endswith(('.mm', '.m', '.h'))
644 for f in input_api.AffectedFiles(file_filter=file_filter):
645 for line_num, line in f.ChangedContents():
646 for func_name, message, error in _BANNED_OBJC_FUNCTIONS:
wnwenbdc444e2016-05-25 13:44:15647 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:59648
649 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
650 for f in input_api.AffectedFiles(file_filter=file_filter):
651 for line_num, line in f.ChangedContents():
[email protected]7345da02012-11-27 14:31:49652 for func_name, message, error, excluded_paths in _BANNED_CPP_FUNCTIONS:
[email protected]7345da02012-11-27 14:31:49653 if IsBlacklisted(f, excluded_paths):
654 continue
wnwenbdc444e2016-05-25 13:44:15655 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:59656
657 result = []
658 if (warnings):
659 result.append(output_api.PresubmitPromptWarning(
660 'Banned functions were used.\n' + '\n'.join(warnings)))
661 if (errors):
662 result.append(output_api.PresubmitError(
663 'Banned functions were used.\n' + '\n'.join(errors)))
664 return result
665
666
[email protected]6c063c62012-07-11 19:11:06667def _CheckNoPragmaOnce(input_api, output_api):
668 """Make sure that banned functions are not used."""
669 files = []
670 pattern = input_api.re.compile(r'^#pragma\s+once',
671 input_api.re.MULTILINE)
672 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
673 if not f.LocalPath().endswith('.h'):
674 continue
675 contents = input_api.ReadFile(f)
676 if pattern.search(contents):
677 files.append(f)
678
679 if files:
680 return [output_api.PresubmitError(
681 'Do not use #pragma once in header files.\n'
682 'See http://www.chromium.org/developers/coding-style#TOC-File-headers',
683 files)]
684 return []
685
[email protected]127f18ec2012-06-16 05:05:59686
[email protected]e7479052012-09-19 00:26:12687def _CheckNoTrinaryTrueFalse(input_api, output_api):
688 """Checks to make sure we don't introduce use of foo ? true : false."""
689 problems = []
690 pattern = input_api.re.compile(r'\?\s*(true|false)\s*:\s*(true|false)')
691 for f in input_api.AffectedFiles():
692 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
693 continue
694
695 for line_num, line in f.ChangedContents():
696 if pattern.match(line):
697 problems.append(' %s:%d' % (f.LocalPath(), line_num))
698
699 if not problems:
700 return []
701 return [output_api.PresubmitPromptWarning(
702 'Please consider avoiding the "? true : false" pattern if possible.\n' +
703 '\n'.join(problems))]
704
705
[email protected]55f9f382012-07-31 11:02:18706def _CheckUnwantedDependencies(input_api, output_api):
707 """Runs checkdeps on #include statements added in this
708 change. Breaking - rules is an error, breaking ! rules is a
709 warning.
710 """
mohan.reddyf21db962014-10-16 12:26:47711 import sys
[email protected]55f9f382012-07-31 11:02:18712 # We need to wait until we have an input_api object and use this
713 # roundabout construct to import checkdeps because this file is
714 # eval-ed and thus doesn't have __file__.
715 original_sys_path = sys.path
716 try:
717 sys.path = sys.path + [input_api.os_path.join(
[email protected]5298cc982014-05-29 20:53:47718 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
[email protected]55f9f382012-07-31 11:02:18719 import checkdeps
720 from cpp_checker import CppChecker
721 from rules import Rule
722 finally:
723 # Restore sys.path to what it was before.
724 sys.path = original_sys_path
725
726 added_includes = []
727 for f in input_api.AffectedFiles():
728 if not CppChecker.IsCppFile(f.LocalPath()):
729 continue
730
731 changed_lines = [line for line_num, line in f.ChangedContents()]
732 added_includes.append([f.LocalPath(), changed_lines])
733
[email protected]26385172013-05-09 23:11:35734 deps_checker = checkdeps.DepsChecker(input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:18735
736 error_descriptions = []
737 warning_descriptions = []
738 for path, rule_type, rule_description in deps_checker.CheckAddedCppIncludes(
739 added_includes):
740 description_with_path = '%s\n %s' % (path, rule_description)
741 if rule_type == Rule.DISALLOW:
742 error_descriptions.append(description_with_path)
743 else:
744 warning_descriptions.append(description_with_path)
745
746 results = []
747 if error_descriptions:
748 results.append(output_api.PresubmitError(
749 'You added one or more #includes that violate checkdeps rules.',
750 error_descriptions))
751 if warning_descriptions:
[email protected]f7051d52013-04-02 18:31:42752 results.append(output_api.PresubmitPromptOrNotify(
[email protected]55f9f382012-07-31 11:02:18753 'You added one or more #includes of files that are temporarily\n'
754 'allowed but being removed. Can you avoid introducing the\n'
755 '#include? See relevant DEPS file(s) for details and contacts.',
756 warning_descriptions))
757 return results
758
759
[email protected]fbcafe5a2012-08-08 15:31:22760def _CheckFilePermissions(input_api, output_api):
761 """Check that all files have their permissions properly set."""
[email protected]791507202014-02-03 23:19:15762 if input_api.platform == 'win32':
763 return []
raphael.kubo.da.costac1d13e60b2016-04-01 11:49:29764 checkperms_tool = input_api.os_path.join(
765 input_api.PresubmitLocalPath(),
766 'tools', 'checkperms', 'checkperms.py')
767 args = [input_api.python_executable, checkperms_tool,
mohan.reddyf21db962014-10-16 12:26:47768 '--root', input_api.change.RepositoryRoot()]
[email protected]fbcafe5a2012-08-08 15:31:22769 for f in input_api.AffectedFiles():
770 args += ['--file', f.LocalPath()]
phajdan.jr5ea54792015-10-14 10:51:11771 try:
772 input_api.subprocess.check_output(args)
773 return []
774 except input_api.subprocess.CalledProcessError as error:
775 return [output_api.PresubmitError(
776 'checkperms.py failed:',
777 long_text=error.output)]
[email protected]fbcafe5a2012-08-08 15:31:22778
779
[email protected]c8278b32012-10-30 20:35:49780def _CheckNoAuraWindowPropertyHInHeaders(input_api, output_api):
781 """Makes sure we don't include ui/aura/window_property.h
782 in header files.
783 """
784 pattern = input_api.re.compile(r'^#include\s*"ui/aura/window_property.h"')
785 errors = []
786 for f in input_api.AffectedFiles():
787 if not f.LocalPath().endswith('.h'):
788 continue
789 for line_num, line in f.ChangedContents():
790 if pattern.match(line):
791 errors.append(' %s:%d' % (f.LocalPath(), line_num))
792
793 results = []
794 if errors:
795 results.append(output_api.PresubmitError(
796 'Header files should not include ui/aura/window_property.h', errors))
797 return results
798
799
[email protected]cf9b78f2012-11-14 11:40:28800def _CheckIncludeOrderForScope(scope, input_api, file_path, changed_linenums):
801 """Checks that the lines in scope occur in the right order.
802
803 1. C system files in alphabetical order
804 2. C++ system files in alphabetical order
805 3. Project's .h files
806 """
807
808 c_system_include_pattern = input_api.re.compile(r'\s*#include <.*\.h>')
809 cpp_system_include_pattern = input_api.re.compile(r'\s*#include <.*>')
810 custom_include_pattern = input_api.re.compile(r'\s*#include ".*')
811
812 C_SYSTEM_INCLUDES, CPP_SYSTEM_INCLUDES, CUSTOM_INCLUDES = range(3)
813
814 state = C_SYSTEM_INCLUDES
815
816 previous_line = ''
[email protected]728b9bb2012-11-14 20:38:57817 previous_line_num = 0
[email protected]cf9b78f2012-11-14 11:40:28818 problem_linenums = []
brucedawson70fadb02015-06-30 17:47:55819 out_of_order = " - line belongs before previous line"
[email protected]cf9b78f2012-11-14 11:40:28820 for line_num, line in scope:
821 if c_system_include_pattern.match(line):
822 if state != C_SYSTEM_INCLUDES:
brucedawson70fadb02015-06-30 17:47:55823 problem_linenums.append((line_num, previous_line_num,
824 " - C system include file in wrong block"))
[email protected]cf9b78f2012-11-14 11:40:28825 elif previous_line and previous_line > line:
brucedawson70fadb02015-06-30 17:47:55826 problem_linenums.append((line_num, previous_line_num,
827 out_of_order))
[email protected]cf9b78f2012-11-14 11:40:28828 elif cpp_system_include_pattern.match(line):
829 if state == C_SYSTEM_INCLUDES:
830 state = CPP_SYSTEM_INCLUDES
831 elif state == CUSTOM_INCLUDES:
brucedawson70fadb02015-06-30 17:47:55832 problem_linenums.append((line_num, previous_line_num,
833 " - c++ system include file in wrong block"))
[email protected]cf9b78f2012-11-14 11:40:28834 elif previous_line and previous_line > line:
brucedawson70fadb02015-06-30 17:47:55835 problem_linenums.append((line_num, previous_line_num, out_of_order))
[email protected]cf9b78f2012-11-14 11:40:28836 elif custom_include_pattern.match(line):
837 if state != CUSTOM_INCLUDES:
838 state = CUSTOM_INCLUDES
839 elif previous_line and previous_line > line:
brucedawson70fadb02015-06-30 17:47:55840 problem_linenums.append((line_num, previous_line_num, out_of_order))
[email protected]cf9b78f2012-11-14 11:40:28841 else:
brucedawson70fadb02015-06-30 17:47:55842 problem_linenums.append((line_num, previous_line_num,
843 "Unknown include type"))
[email protected]cf9b78f2012-11-14 11:40:28844 previous_line = line
[email protected]728b9bb2012-11-14 20:38:57845 previous_line_num = line_num
[email protected]cf9b78f2012-11-14 11:40:28846
847 warnings = []
brucedawson70fadb02015-06-30 17:47:55848 for (line_num, previous_line_num, failure_type) in problem_linenums:
[email protected]728b9bb2012-11-14 20:38:57849 if line_num in changed_linenums or previous_line_num in changed_linenums:
brucedawson70fadb02015-06-30 17:47:55850 warnings.append(' %s:%d:%s' % (file_path, line_num, failure_type))
[email protected]cf9b78f2012-11-14 11:40:28851 return warnings
852
853
[email protected]ac294a12012-12-06 16:38:43854def _CheckIncludeOrderInFile(input_api, f, changed_linenums):
[email protected]cf9b78f2012-11-14 11:40:28855 """Checks the #include order for the given file f."""
856
[email protected]2299dcf2012-11-15 19:56:24857 system_include_pattern = input_api.re.compile(r'\s*#include \<.*')
[email protected]23093b62013-09-20 12:16:30858 # Exclude the following includes from the check:
859 # 1) #include <.../...>, e.g., <sys/...> includes often need to appear in a
860 # specific order.
861 # 2) <atlbase.h>, "build/build_config.h"
862 excluded_include_pattern = input_api.re.compile(
863 r'\s*#include (\<.*/.*|\<atlbase\.h\>|"build/build_config.h")')
[email protected]2299dcf2012-11-15 19:56:24864 custom_include_pattern = input_api.re.compile(r'\s*#include "(?P<FILE>.*)"')
[email protected]3e83618c2013-10-09 22:32:33865 # Match the final or penultimate token if it is xxxtest so we can ignore it
866 # when considering the special first include.
867 test_file_tag_pattern = input_api.re.compile(
868 r'_[a-z]+test(?=(_[a-zA-Z0-9]+)?\.)')
[email protected]0e5c1852012-12-18 20:17:11869 if_pattern = input_api.re.compile(
870 r'\s*#\s*(if|elif|else|endif|define|undef).*')
871 # Some files need specialized order of includes; exclude such files from this
872 # check.
873 uncheckable_includes_pattern = input_api.re.compile(
874 r'\s*#include '
875 '("ipc/.*macros\.h"|<windows\.h>|".*gl.*autogen.h")\s*')
[email protected]cf9b78f2012-11-14 11:40:28876
877 contents = f.NewContents()
878 warnings = []
879 line_num = 0
880
[email protected]ac294a12012-12-06 16:38:43881 # Handle the special first include. If the first include file is
882 # some/path/file.h, the corresponding including file can be some/path/file.cc,
883 # some/other/path/file.cc, some/path/file_platform.cc, some/path/file-suffix.h
884 # etc. It's also possible that no special first include exists.
[email protected]3e83618c2013-10-09 22:32:33885 # If the included file is some/path/file_platform.h the including file could
886 # also be some/path/file_xxxtest_platform.h.
887 including_file_base_name = test_file_tag_pattern.sub(
888 '', input_api.os_path.basename(f.LocalPath()))
889
[email protected]ac294a12012-12-06 16:38:43890 for line in contents:
891 line_num += 1
892 if system_include_pattern.match(line):
893 # No special first include -> process the line again along with normal
894 # includes.
895 line_num -= 1
896 break
897 match = custom_include_pattern.match(line)
898 if match:
899 match_dict = match.groupdict()
[email protected]3e83618c2013-10-09 22:32:33900 header_basename = test_file_tag_pattern.sub(
901 '', input_api.os_path.basename(match_dict['FILE'])).replace('.h', '')
902
903 if header_basename not in including_file_base_name:
[email protected]2299dcf2012-11-15 19:56:24904 # No special first include -> process the line again along with normal
905 # includes.
906 line_num -= 1
[email protected]ac294a12012-12-06 16:38:43907 break
[email protected]cf9b78f2012-11-14 11:40:28908
909 # Split into scopes: Each region between #if and #endif is its own scope.
910 scopes = []
911 current_scope = []
912 for line in contents[line_num:]:
913 line_num += 1
[email protected]0e5c1852012-12-18 20:17:11914 if uncheckable_includes_pattern.match(line):
[email protected]4436c9e2014-01-07 23:19:54915 continue
[email protected]2309b0fa02012-11-16 12:18:27916 if if_pattern.match(line):
[email protected]cf9b78f2012-11-14 11:40:28917 scopes.append(current_scope)
918 current_scope = []
[email protected]962f117e2012-11-22 18:11:56919 elif ((system_include_pattern.match(line) or
920 custom_include_pattern.match(line)) and
921 not excluded_include_pattern.match(line)):
[email protected]cf9b78f2012-11-14 11:40:28922 current_scope.append((line_num, line))
923 scopes.append(current_scope)
924
925 for scope in scopes:
926 warnings.extend(_CheckIncludeOrderForScope(scope, input_api, f.LocalPath(),
927 changed_linenums))
928 return warnings
929
930
931def _CheckIncludeOrder(input_api, output_api):
932 """Checks that the #include order is correct.
933
934 1. The corresponding header for source files.
935 2. C system files in alphabetical order
936 3. C++ system files in alphabetical order
937 4. Project's .h files in alphabetical order
938
[email protected]ac294a12012-12-06 16:38:43939 Each region separated by #if, #elif, #else, #endif, #define and #undef follows
940 these rules separately.
[email protected]cf9b78f2012-11-14 11:40:28941 """
[email protected]e120b012014-08-15 19:08:35942 def FileFilterIncludeOrder(affected_file):
943 black_list = (_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
944 return input_api.FilterSourceFile(affected_file, black_list=black_list)
[email protected]cf9b78f2012-11-14 11:40:28945
946 warnings = []
[email protected]e120b012014-08-15 19:08:35947 for f in input_api.AffectedFiles(file_filter=FileFilterIncludeOrder):
tapted574f09c2015-05-19 13:08:08948 if f.LocalPath().endswith(('.cc', '.h', '.mm')):
[email protected]ac294a12012-12-06 16:38:43949 changed_linenums = set(line_num for line_num, _ in f.ChangedContents())
950 warnings.extend(_CheckIncludeOrderInFile(input_api, f, changed_linenums))
[email protected]cf9b78f2012-11-14 11:40:28951
952 results = []
953 if warnings:
[email protected]f7051d52013-04-02 18:31:42954 results.append(output_api.PresubmitPromptOrNotify(_INCLUDE_ORDER_WARNING,
[email protected]120cf540d2012-12-10 17:55:53955 warnings))
[email protected]cf9b78f2012-11-14 11:40:28956 return results
957
958
[email protected]70ca77752012-11-20 03:45:03959def _CheckForVersionControlConflictsInFile(input_api, f):
960 pattern = input_api.re.compile('^(?:<<<<<<<|>>>>>>>) |^=======$')
961 errors = []
962 for line_num, line in f.ChangedContents():
dbeam95c35a2f2015-06-02 01:40:23963 if f.LocalPath().endswith('.md'):
964 # First-level headers in markdown look a lot like version control
965 # conflict markers. http://daringfireball.net/projects/markdown/basics
966 continue
[email protected]70ca77752012-11-20 03:45:03967 if pattern.match(line):
968 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
969 return errors
970
971
972def _CheckForVersionControlConflicts(input_api, output_api):
973 """Usually this is not intentional and will cause a compile failure."""
974 errors = []
975 for f in input_api.AffectedFiles():
976 errors.extend(_CheckForVersionControlConflictsInFile(input_api, f))
977
978 results = []
979 if errors:
980 results.append(output_api.PresubmitError(
981 'Version control conflict markers found, please resolve.', errors))
982 return results
983
984
[email protected]06e6d0ff2012-12-11 01:36:44985def _CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api):
986 def FilterFile(affected_file):
987 """Filter function for use with input_api.AffectedSourceFiles,
988 below. This filters out everything except non-test files from
989 top-level directories that generally speaking should not hard-code
990 service URLs (e.g. src/android_webview/, src/content/ and others).
991 """
992 return input_api.FilterSourceFile(
993 affected_file,
[email protected]78bb39d62012-12-11 15:11:56994 white_list=(r'^(android_webview|base|content|net)[\\\/].*', ),
[email protected]06e6d0ff2012-12-11 01:36:44995 black_list=(_EXCLUDED_PATHS +
996 _TEST_CODE_EXCLUDED_PATHS +
997 input_api.DEFAULT_BLACK_LIST))
998
reillyi38965732015-11-16 18:27:33999 base_pattern = ('"[^"]*(google|googleapis|googlezip|googledrive|appspot)'
1000 '\.(com|net)[^"]*"')
[email protected]de4f7d22013-05-23 14:27:461001 comment_pattern = input_api.re.compile('//.*%s' % base_pattern)
1002 pattern = input_api.re.compile(base_pattern)
[email protected]06e6d0ff2012-12-11 01:36:441003 problems = [] # items are (filename, line_number, line)
1004 for f in input_api.AffectedSourceFiles(FilterFile):
1005 for line_num, line in f.ChangedContents():
[email protected]de4f7d22013-05-23 14:27:461006 if not comment_pattern.search(line) and pattern.search(line):
[email protected]06e6d0ff2012-12-11 01:36:441007 problems.append((f.LocalPath(), line_num, line))
1008
1009 if problems:
[email protected]f7051d52013-04-02 18:31:421010 return [output_api.PresubmitPromptOrNotify(
[email protected]06e6d0ff2012-12-11 01:36:441011 'Most layers below src/chrome/ should not hardcode service URLs.\n'
[email protected]b0149772014-03-27 16:47:581012 'Are you sure this is correct?',
[email protected]06e6d0ff2012-12-11 01:36:441013 [' %s:%d: %s' % (
1014 problem[0], problem[1], problem[2]) for problem in problems])]
[email protected]2fdd1f362013-01-16 03:56:031015 else:
1016 return []
[email protected]06e6d0ff2012-12-11 01:36:441017
1018
[email protected]d2530012013-01-25 16:39:271019def _CheckNoAbbreviationInPngFileName(input_api, output_api):
1020 """Makes sure there are no abbreviations in the name of PNG files.
binji0dcdf342014-12-12 18:32:311021 The native_client_sdk directory is excluded because it has auto-generated PNG
1022 files for documentation.
[email protected]d2530012013-01-25 16:39:271023 """
[email protected]d2530012013-01-25 16:39:271024 errors = []
binji0dcdf342014-12-12 18:32:311025 white_list = (r'.*_[a-z]_.*\.png$|.*_[a-z]\.png$',)
1026 black_list = (r'^native_client_sdk[\\\/]',)
1027 file_filter = lambda f: input_api.FilterSourceFile(
1028 f, white_list=white_list, black_list=black_list)
1029 for f in input_api.AffectedFiles(include_deletes=False,
1030 file_filter=file_filter):
1031 errors.append(' %s' % f.LocalPath())
[email protected]d2530012013-01-25 16:39:271032
1033 results = []
1034 if errors:
1035 results.append(output_api.PresubmitError(
1036 'The name of PNG files should not have abbreviations. \n'
1037 'Use _hover.png, _center.png, instead of _h.png, _c.png.\n'
1038 'Contact [email protected] if you have questions.', errors))
1039 return results
1040
1041
[email protected]14a6131c2014-01-08 01:15:411042def _FilesToCheckForIncomingDeps(re, changed_lines):
[email protected]f32e2d1e2013-07-26 21:39:081043 """Helper method for _CheckAddedDepsHaveTargetApprovals. Returns
[email protected]14a6131c2014-01-08 01:15:411044 a set of DEPS entries that we should look up.
1045
1046 For a directory (rather than a specific filename) we fake a path to
1047 a specific filename by adding /DEPS. This is chosen as a file that
1048 will seldom or never be subject to per-file include_rules.
1049 """
[email protected]2b438d62013-11-14 17:54:141050 # We ignore deps entries on auto-generated directories.
1051 AUTO_GENERATED_DIRS = ['grit', 'jni']
[email protected]f32e2d1e2013-07-26 21:39:081052
1053 # This pattern grabs the path without basename in the first
1054 # parentheses, and the basename (if present) in the second. It
1055 # relies on the simple heuristic that if there is a basename it will
1056 # be a header file ending in ".h".
1057 pattern = re.compile(
1058 r"""['"]\+([^'"]+?)(/[a-zA-Z0-9_]+\.h)?['"].*""")
[email protected]2b438d62013-11-14 17:54:141059 results = set()
[email protected]f32e2d1e2013-07-26 21:39:081060 for changed_line in changed_lines:
1061 m = pattern.match(changed_line)
1062 if m:
1063 path = m.group(1)
[email protected]2b438d62013-11-14 17:54:141064 if path.split('/')[0] not in AUTO_GENERATED_DIRS:
[email protected]14a6131c2014-01-08 01:15:411065 if m.group(2):
1066 results.add('%s%s' % (path, m.group(2)))
1067 else:
1068 results.add('%s/DEPS' % path)
[email protected]f32e2d1e2013-07-26 21:39:081069 return results
1070
1071
[email protected]e871964c2013-05-13 14:14:551072def _CheckAddedDepsHaveTargetApprovals(input_api, output_api):
1073 """When a dependency prefixed with + is added to a DEPS file, we
1074 want to make sure that the change is reviewed by an OWNER of the
1075 target file or directory, to avoid layering violations from being
1076 introduced. This check verifies that this happens.
1077 """
1078 changed_lines = set()
jochen53efcdd2016-01-29 05:09:241079
1080 file_filter = lambda f: not input_api.re.match(
1081 r"^third_party[\\\/]WebKit[\\\/].*", f.LocalPath())
1082 for f in input_api.AffectedFiles(include_deletes=False,
1083 file_filter=file_filter):
[email protected]e871964c2013-05-13 14:14:551084 filename = input_api.os_path.basename(f.LocalPath())
1085 if filename == 'DEPS':
1086 changed_lines |= set(line.strip()
1087 for line_num, line
1088 in f.ChangedContents())
1089 if not changed_lines:
1090 return []
1091
[email protected]14a6131c2014-01-08 01:15:411092 virtual_depended_on_files = _FilesToCheckForIncomingDeps(input_api.re,
1093 changed_lines)
[email protected]e871964c2013-05-13 14:14:551094 if not virtual_depended_on_files:
1095 return []
1096
1097 if input_api.is_committing:
1098 if input_api.tbr:
1099 return [output_api.PresubmitNotifyResult(
1100 '--tbr was specified, skipping OWNERS check for DEPS additions')]
Paweł Hajdan, Jrbe6739ea2016-04-28 15:07:271101 if input_api.dry_run:
1102 return [output_api.PresubmitNotifyResult(
1103 'This is a dry run, skipping OWNERS check for DEPS additions')]
[email protected]e871964c2013-05-13 14:14:551104 if not input_api.change.issue:
1105 return [output_api.PresubmitError(
1106 "DEPS approval by OWNERS check failed: this change has "
1107 "no Rietveld issue number, so we can't check it for approvals.")]
1108 output = output_api.PresubmitError
1109 else:
1110 output = output_api.PresubmitNotifyResult
1111
1112 owners_db = input_api.owners_db
tandriied3b7e12016-05-12 14:38:501113 owner_email, reviewers = (
1114 input_api.canned_checks.GetCodereviewOwnerAndReviewers(
1115 input_api,
1116 owners_db.email_regexp,
1117 approval_needed=input_api.is_committing))
[email protected]e871964c2013-05-13 14:14:551118
1119 owner_email = owner_email or input_api.change.author_email
1120
[email protected]de4f7d22013-05-23 14:27:461121 reviewers_plus_owner = set(reviewers)
[email protected]e71c6082013-05-22 02:28:511122 if owner_email:
[email protected]de4f7d22013-05-23 14:27:461123 reviewers_plus_owner.add(owner_email)
[email protected]e871964c2013-05-13 14:14:551124 missing_files = owners_db.files_not_covered_by(virtual_depended_on_files,
1125 reviewers_plus_owner)
[email protected]14a6131c2014-01-08 01:15:411126
1127 # We strip the /DEPS part that was added by
1128 # _FilesToCheckForIncomingDeps to fake a path to a file in a
1129 # directory.
1130 def StripDeps(path):
1131 start_deps = path.rfind('/DEPS')
1132 if start_deps != -1:
1133 return path[:start_deps]
1134 else:
1135 return path
1136 unapproved_dependencies = ["'+%s'," % StripDeps(path)
[email protected]e871964c2013-05-13 14:14:551137 for path in missing_files]
1138
1139 if unapproved_dependencies:
1140 output_list = [
Paweł Hajdan, Jrec17f882016-07-04 14:16:151141 output('You need LGTM from owners of depends-on paths in DEPS that were '
1142 'modified in this CL:\n %s' %
1143 '\n '.join(sorted(unapproved_dependencies)))]
1144 suggested_owners = owners_db.reviewers_for(missing_files, owner_email)
1145 output_list.append(output(
1146 'Suggested missing target path OWNERS:\n %s' %
1147 '\n '.join(suggested_owners or [])))
[email protected]e871964c2013-05-13 14:14:551148 return output_list
1149
1150 return []
1151
1152
[email protected]85218562013-11-22 07:41:401153def _CheckSpamLogging(input_api, output_api):
1154 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
1155 black_list = (_EXCLUDED_PATHS +
1156 _TEST_CODE_EXCLUDED_PATHS +
1157 input_api.DEFAULT_BLACK_LIST +
[email protected]6f742dd02013-11-26 23:19:501158 (r"^base[\\\/]logging\.h$",
[email protected]80f360a2014-01-23 01:36:191159 r"^base[\\\/]logging\.cc$",
[email protected]8dc338c2013-12-09 16:28:481160 r"^chrome[\\\/]app[\\\/]chrome_main_delegate\.cc$",
[email protected]6e268db2013-12-04 01:41:461161 r"^chrome[\\\/]browser[\\\/]chrome_browser_main\.cc$",
[email protected]4de75262013-12-18 23:16:121162 r"^chrome[\\\/]browser[\\\/]ui[\\\/]startup[\\\/]"
1163 r"startup_browser_creator\.cc$",
[email protected]fe0e6e12013-12-04 05:52:581164 r"^chrome[\\\/]installer[\\\/]setup[\\\/].*",
[email protected]8cf6f842014-08-08 21:33:161165 r"chrome[\\\/]browser[\\\/]diagnostics[\\\/]" +
[email protected]f5b9a3f342014-08-08 22:06:031166 r"diagnostics_writer\.cc$",
[email protected]9f13b602014-08-07 02:59:151167 r"^chrome_elf[\\\/]dll_hash[\\\/]dll_hash_main\.cc$",
1168 r"^chromecast[\\\/]",
1169 r"^cloud_print[\\\/]",
jochen34415e52015-07-10 08:34:311170 r"^components[\\\/]html_viewer[\\\/]"
1171 r"web_test_delegate_impl\.cc$",
peter80739bb2015-10-20 11:17:461172 # TODO(peter): Remove this exception. https://crbug.com/534537
1173 r"^content[\\\/]browser[\\\/]notifications[\\\/]"
1174 r"notification_event_dispatcher_impl\.cc$",
[email protected]9056e732014-01-08 06:25:251175 r"^content[\\\/]common[\\\/]gpu[\\\/]client[\\\/]"
1176 r"gl_helper_benchmark\.cc$",
altimin979ea2e12016-05-18 16:16:241177 r"^courgette[\\\/]courgette_minimal_tool\.cc$",
thestigc9e38a22014-09-13 01:02:111178 r"^courgette[\\\/]courgette_tool\.cc$",
[email protected]9f13b602014-08-07 02:59:151179 r"^extensions[\\\/]renderer[\\\/]logging_native_handler\.cc$",
prashant.nb0252f62014-11-08 05:02:111180 r"^ipc[\\\/]ipc_logging\.cc$",
[email protected]9c36d922014-03-24 16:47:521181 r"^native_client_sdk[\\\/]",
[email protected]cdbdced2013-11-27 21:35:501182 r"^remoting[\\\/]base[\\\/]logging\.h$",
[email protected]67c96ab2013-12-17 02:05:361183 r"^remoting[\\\/]host[\\\/].*",
[email protected]8232f8fd2013-12-14 00:52:311184 r"^sandbox[\\\/]linux[\\\/].*",
[email protected]0b7a21e2014-02-11 18:38:131185 r"^tools[\\\/]",
thestig22dfc4012014-09-05 08:29:441186 r"^ui[\\\/]aura[\\\/]bench[\\\/]bench_main\.cc$",
halliwellf7fc61c62016-01-28 17:18:451187 r"^ui[\\\/]ozone[\\\/]platform[\\\/]cast[\\\/]",
vchigrin14251492015-01-12 08:09:021188 r"^storage[\\\/]browser[\\\/]fileapi[\\\/]" +
thestig22dfc4012014-09-05 08:29:441189 r"dump_file_system.cc$",))
[email protected]85218562013-11-22 07:41:401190 source_file_filter = lambda x: input_api.FilterSourceFile(
1191 x, white_list=(file_inclusion_pattern,), black_list=black_list)
1192
1193 log_info = []
1194 printf = []
1195
1196 for f in input_api.AffectedSourceFiles(source_file_filter):
1197 contents = input_api.ReadFile(f, 'rb')
mohan.reddyf21db962014-10-16 12:26:471198 if input_api.re.search(r"\bD?LOG\s*\(\s*INFO\s*\)", contents):
[email protected]85218562013-11-22 07:41:401199 log_info.append(f.LocalPath())
mohan.reddyf21db962014-10-16 12:26:471200 elif input_api.re.search(r"\bD?LOG_IF\s*\(\s*INFO\s*,", contents):
[email protected]85210652013-11-28 05:50:131201 log_info.append(f.LocalPath())
[email protected]18b466b2013-12-02 22:01:371202
mohan.reddyf21db962014-10-16 12:26:471203 if input_api.re.search(r"\bprintf\(", contents):
[email protected]18b466b2013-12-02 22:01:371204 printf.append(f.LocalPath())
mohan.reddyf21db962014-10-16 12:26:471205 elif input_api.re.search(r"\bfprintf\((stdout|stderr)", contents):
[email protected]85218562013-11-22 07:41:401206 printf.append(f.LocalPath())
1207
1208 if log_info:
1209 return [output_api.PresubmitError(
1210 'These files spam the console log with LOG(INFO):',
1211 items=log_info)]
1212 if printf:
1213 return [output_api.PresubmitError(
1214 'These files spam the console log with printf/fprintf:',
1215 items=printf)]
1216 return []
1217
1218
[email protected]49aa76a2013-12-04 06:59:161219def _CheckForAnonymousVariables(input_api, output_api):
1220 """These types are all expected to hold locks while in scope and
1221 so should never be anonymous (which causes them to be immediately
1222 destroyed)."""
1223 they_who_must_be_named = [
1224 'base::AutoLock',
1225 'base::AutoReset',
1226 'base::AutoUnlock',
1227 'SkAutoAlphaRestore',
1228 'SkAutoBitmapShaderInstall',
1229 'SkAutoBlitterChoose',
1230 'SkAutoBounderCommit',
1231 'SkAutoCallProc',
1232 'SkAutoCanvasRestore',
1233 'SkAutoCommentBlock',
1234 'SkAutoDescriptor',
1235 'SkAutoDisableDirectionCheck',
1236 'SkAutoDisableOvalCheck',
1237 'SkAutoFree',
1238 'SkAutoGlyphCache',
1239 'SkAutoHDC',
1240 'SkAutoLockColors',
1241 'SkAutoLockPixels',
1242 'SkAutoMalloc',
1243 'SkAutoMaskFreeImage',
1244 'SkAutoMutexAcquire',
1245 'SkAutoPathBoundsUpdate',
1246 'SkAutoPDFRelease',
1247 'SkAutoRasterClipValidate',
1248 'SkAutoRef',
1249 'SkAutoTime',
1250 'SkAutoTrace',
1251 'SkAutoUnref',
1252 ]
1253 anonymous = r'(%s)\s*[({]' % '|'.join(they_who_must_be_named)
1254 # bad: base::AutoLock(lock.get());
1255 # not bad: base::AutoLock lock(lock.get());
1256 bad_pattern = input_api.re.compile(anonymous)
1257 # good: new base::AutoLock(lock.get())
1258 good_pattern = input_api.re.compile(r'\bnew\s*' + anonymous)
1259 errors = []
1260
1261 for f in input_api.AffectedFiles():
1262 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
1263 continue
1264 for linenum, line in f.ChangedContents():
1265 if bad_pattern.search(line) and not good_pattern.search(line):
1266 errors.append('%s:%d' % (f.LocalPath(), linenum))
1267
1268 if errors:
1269 return [output_api.PresubmitError(
1270 'These lines create anonymous variables that need to be named:',
1271 items=errors)]
1272 return []
1273
1274
[email protected]5fe0f8742013-11-29 01:04:591275def _CheckCygwinShell(input_api, output_api):
1276 source_file_filter = lambda x: input_api.FilterSourceFile(
1277 x, white_list=(r'.+\.(gyp|gypi)$',))
1278 cygwin_shell = []
1279
1280 for f in input_api.AffectedSourceFiles(source_file_filter):
1281 for linenum, line in f.ChangedContents():
1282 if 'msvs_cygwin_shell' in line:
1283 cygwin_shell.append(f.LocalPath())
1284 break
1285
1286 if cygwin_shell:
1287 return [output_api.PresubmitError(
1288 'These files should not use msvs_cygwin_shell (the default is 0):',
1289 items=cygwin_shell)]
1290 return []
1291
[email protected]85218562013-11-22 07:41:401292
[email protected]999261d2014-03-03 20:08:081293def _CheckUserActionUpdate(input_api, output_api):
1294 """Checks if any new user action has been added."""
[email protected]2f92dec2014-03-07 19:21:521295 if any('actions.xml' == input_api.os_path.basename(f) for f in
[email protected]999261d2014-03-03 20:08:081296 input_api.LocalPaths()):
[email protected]2f92dec2014-03-07 19:21:521297 # If actions.xml is already included in the changelist, the PRESUBMIT
1298 # for actions.xml will do a more complete presubmit check.
[email protected]999261d2014-03-03 20:08:081299 return []
1300
[email protected]999261d2014-03-03 20:08:081301 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm'))
1302 action_re = r'[^a-zA-Z]UserMetricsAction\("([^"]*)'
[email protected]2f92dec2014-03-07 19:21:521303 current_actions = None
[email protected]999261d2014-03-03 20:08:081304 for f in input_api.AffectedFiles(file_filter=file_filter):
1305 for line_num, line in f.ChangedContents():
1306 match = input_api.re.search(action_re, line)
1307 if match:
[email protected]2f92dec2014-03-07 19:21:521308 # Loads contents in tools/metrics/actions/actions.xml to memory. It's
1309 # loaded only once.
1310 if not current_actions:
1311 with open('tools/metrics/actions/actions.xml') as actions_f:
1312 current_actions = actions_f.read()
1313 # Search for the matched user action name in |current_actions|.
[email protected]999261d2014-03-03 20:08:081314 for action_name in match.groups():
[email protected]2f92dec2014-03-07 19:21:521315 action = 'name="{0}"'.format(action_name)
1316 if action not in current_actions:
[email protected]999261d2014-03-03 20:08:081317 return [output_api.PresubmitPromptWarning(
1318 'File %s line %d: %s is missing in '
[email protected]2f92dec2014-03-07 19:21:521319 'tools/metrics/actions/actions.xml. Please run '
1320 'tools/metrics/actions/extract_actions.py to update.'
[email protected]999261d2014-03-03 20:08:081321 % (f.LocalPath(), line_num, action_name))]
1322 return []
1323
1324
[email protected]99171a92014-06-03 08:44:471325def _GetJSONParseError(input_api, filename, eat_comments=True):
1326 try:
1327 contents = input_api.ReadFile(filename)
1328 if eat_comments:
plundblad1f5a4509f2015-07-23 11:31:131329 import sys
1330 original_sys_path = sys.path
1331 try:
1332 sys.path = sys.path + [input_api.os_path.join(
1333 input_api.PresubmitLocalPath(),
1334 'tools', 'json_comment_eater')]
1335 import json_comment_eater
1336 finally:
1337 sys.path = original_sys_path
1338 contents = json_comment_eater.Nom(contents)
[email protected]99171a92014-06-03 08:44:471339
1340 input_api.json.loads(contents)
1341 except ValueError as e:
1342 return e
1343 return None
1344
1345
1346def _GetIDLParseError(input_api, filename):
1347 try:
1348 contents = input_api.ReadFile(filename)
1349 idl_schema = input_api.os_path.join(
1350 input_api.PresubmitLocalPath(),
1351 'tools', 'json_schema_compiler', 'idl_schema.py')
1352 process = input_api.subprocess.Popen(
1353 [input_api.python_executable, idl_schema],
1354 stdin=input_api.subprocess.PIPE,
1355 stdout=input_api.subprocess.PIPE,
1356 stderr=input_api.subprocess.PIPE,
1357 universal_newlines=True)
1358 (_, error) = process.communicate(input=contents)
1359 return error or None
1360 except ValueError as e:
1361 return e
1362
1363
1364def _CheckParseErrors(input_api, output_api):
1365 """Check that IDL and JSON files do not contain syntax errors."""
1366 actions = {
1367 '.idl': _GetIDLParseError,
1368 '.json': _GetJSONParseError,
1369 }
1370 # These paths contain test data and other known invalid JSON files.
1371 excluded_patterns = [
joaodasilva718f87672014-08-30 09:25:491372 r'test[\\\/]data[\\\/]',
1373 r'^components[\\\/]policy[\\\/]resources[\\\/]policy_templates\.json$',
[email protected]99171a92014-06-03 08:44:471374 ]
1375 # Most JSON files are preprocessed and support comments, but these do not.
1376 json_no_comments_patterns = [
joaodasilva718f87672014-08-30 09:25:491377 r'^testing[\\\/]',
[email protected]99171a92014-06-03 08:44:471378 ]
1379 # Only run IDL checker on files in these directories.
1380 idl_included_patterns = [
joaodasilva718f87672014-08-30 09:25:491381 r'^chrome[\\\/]common[\\\/]extensions[\\\/]api[\\\/]',
1382 r'^extensions[\\\/]common[\\\/]api[\\\/]',
[email protected]99171a92014-06-03 08:44:471383 ]
1384
1385 def get_action(affected_file):
1386 filename = affected_file.LocalPath()
1387 return actions.get(input_api.os_path.splitext(filename)[1])
1388
1389 def MatchesFile(patterns, path):
1390 for pattern in patterns:
1391 if input_api.re.search(pattern, path):
1392 return True
1393 return False
1394
1395 def FilterFile(affected_file):
1396 action = get_action(affected_file)
1397 if not action:
1398 return False
1399 path = affected_file.LocalPath()
1400
1401 if MatchesFile(excluded_patterns, path):
1402 return False
1403
1404 if (action == _GetIDLParseError and
1405 not MatchesFile(idl_included_patterns, path)):
1406 return False
1407 return True
1408
1409 results = []
1410 for affected_file in input_api.AffectedFiles(
1411 file_filter=FilterFile, include_deletes=False):
1412 action = get_action(affected_file)
1413 kwargs = {}
1414 if (action == _GetJSONParseError and
1415 MatchesFile(json_no_comments_patterns, affected_file.LocalPath())):
1416 kwargs['eat_comments'] = False
1417 parse_error = action(input_api,
1418 affected_file.AbsoluteLocalPath(),
1419 **kwargs)
1420 if parse_error:
1421 results.append(output_api.PresubmitError('%s could not be parsed: %s' %
1422 (affected_file.LocalPath(), parse_error)))
1423 return results
1424
1425
[email protected]760deea2013-12-10 19:33:491426def _CheckJavaStyle(input_api, output_api):
1427 """Runs checkstyle on changed java files and returns errors if any exist."""
mohan.reddyf21db962014-10-16 12:26:471428 import sys
[email protected]760deea2013-12-10 19:33:491429 original_sys_path = sys.path
1430 try:
1431 sys.path = sys.path + [input_api.os_path.join(
1432 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkstyle')]
1433 import checkstyle
1434 finally:
1435 # Restore sys.path to what it was before.
1436 sys.path = original_sys_path
1437
1438 return checkstyle.RunCheckstyle(
davileen72d76532015-01-20 22:30:091439 input_api, output_api, 'tools/android/checkstyle/chromium-style-5.0.xml',
newtd8b7d30e92015-01-23 18:10:511440 black_list=_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
[email protected]760deea2013-12-10 19:33:491441
1442
dchenge07de812016-06-20 19:27:171443def _CheckIpcOwners(input_api, output_api):
1444 """Checks that affected files involving IPC have an IPC OWNERS rule.
1445
1446 Whether or not a file affects IPC is determined by a simple whitelist of
1447 filename patterns."""
1448 file_patterns = [
1449 '*_messages.cc',
1450 '*_messages*.h',
1451 '*_param_traits*.*',
1452 '*.mojom',
1453 '*_struct_traits*.*',
1454 '*_type_converter*.*',
1455 # Blink uses a different file naming convention
1456 '*StructTraits*.*',
1457 '*TypeConverter*.*',
1458 ]
1459
scottmg7a6ed5ba2016-11-04 18:22:041460 # These third_party directories do not contain IPCs, but contain files
1461 # matching the above patterns, which trigger false positives.
1462 exclude_paths = [
1463 'third_party/crashpad/*',
1464 ]
1465
dchenge07de812016-06-20 19:27:171466 # Dictionary mapping an OWNERS file path to Patterns.
1467 # Patterns is a dictionary mapping glob patterns (suitable for use in per-file
1468 # rules ) to a PatternEntry.
1469 # PatternEntry is a dictionary with two keys:
1470 # - 'files': the files that are matched by this pattern
1471 # - 'rules': the per-file rules needed for this pattern
1472 # For example, if we expect OWNERS file to contain rules for *.mojom and
1473 # *_struct_traits*.*, Patterns might look like this:
1474 # {
1475 # '*.mojom': {
1476 # 'files': ...,
1477 # 'rules': [
1478 # 'per-file *.mojom=set noparent',
1479 # 'per-file *.mojom=file://ipc/SECURITY_OWNERS',
1480 # ],
1481 # },
1482 # '*_struct_traits*.*': {
1483 # 'files': ...,
1484 # 'rules': [
1485 # 'per-file *_struct_traits*.*=set noparent',
1486 # 'per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS',
1487 # ],
1488 # },
1489 # }
1490 to_check = {}
1491
1492 # Iterate through the affected files to see what we actually need to check
1493 # for. We should only nag patch authors about per-file rules if a file in that
1494 # directory would match that pattern. If a directory only contains *.mojom
1495 # files and no *_messages*.h files, we should only nag about rules for
1496 # *.mojom files.
rockot51249332016-06-23 16:32:251497 for f in input_api.change.AffectedFiles(include_deletes=False):
dchenge07de812016-06-20 19:27:171498 for pattern in file_patterns:
1499 if input_api.fnmatch.fnmatch(
1500 input_api.os_path.basename(f.LocalPath()), pattern):
scottmg7a6ed5ba2016-11-04 18:22:041501 skip = False
1502 for exclude in exclude_paths:
1503 if input_api.fnmatch.fnmatch(f.LocalPath(), exclude):
1504 skip = True
1505 break
1506 if skip:
1507 continue
dchenge07de812016-06-20 19:27:171508 owners_file = input_api.os_path.join(
1509 input_api.os_path.dirname(f.LocalPath()), 'OWNERS')
1510 if owners_file not in to_check:
1511 to_check[owners_file] = {}
1512 if pattern not in to_check[owners_file]:
1513 to_check[owners_file][pattern] = {
1514 'files': [],
1515 'rules': [
1516 'per-file %s=set noparent' % pattern,
1517 'per-file %s=file://ipc/SECURITY_OWNERS' % pattern,
1518 ]
1519 }
1520 to_check[owners_file][pattern]['files'].append(f)
1521 break
1522
1523 # Now go through the OWNERS files we collected, filtering out rules that are
1524 # already present in that OWNERS file.
1525 for owners_file, patterns in to_check.iteritems():
1526 try:
1527 with file(owners_file) as f:
1528 lines = set(f.read().splitlines())
1529 for entry in patterns.itervalues():
1530 entry['rules'] = [rule for rule in entry['rules'] if rule not in lines
1531 ]
1532 except IOError:
1533 # No OWNERS file, so all the rules are definitely missing.
1534 continue
1535
1536 # All the remaining lines weren't found in OWNERS files, so emit an error.
1537 errors = []
1538 for owners_file, patterns in to_check.iteritems():
1539 missing_lines = []
1540 files = []
1541 for pattern, entry in patterns.iteritems():
1542 missing_lines.extend(entry['rules'])
1543 files.extend([' %s' % f.LocalPath() for f in entry['files']])
1544 if missing_lines:
1545 errors.append(
1546 '%s is missing the following lines:\n\n%s\n\nfor changed files:\n%s' %
1547 (owners_file, '\n'.join(missing_lines), '\n'.join(files)))
1548
1549 results = []
1550 if errors:
vabrf5ce3bf92016-07-11 14:52:411551 if input_api.is_committing:
1552 output = output_api.PresubmitError
1553 else:
1554 output = output_api.PresubmitPromptWarning
1555 results.append(output(
dchenge07de812016-06-20 19:27:171556 'Found changes to IPC files without a security OWNER!',
1557 long_text='\n\n'.join(errors)))
1558
1559 return results
1560
1561
yzshend99f726a2016-07-25 21:44:231562def _CheckMojoUsesNewWrapperTypes(input_api, output_api):
1563 """Checks to make sure that all newly added mojom targets map array/map/string
1564 to STL (for chromium) or WTF (for blink) types.
1565 TODO(yzshen): remove this check once crbug.com/624136 is completed.
1566 """
1567 files = []
1568 pattern = input_api.re.compile(r'use_new_wrapper_types.*false',
1569 input_api.re.MULTILINE)
1570
1571 for f in input_api.AffectedFiles():
1572 if not f.LocalPath().endswith(('.gyp', '.gypi', 'gn', 'gni')):
1573 continue
1574
1575 for _, line in f.ChangedContents():
1576 if pattern.search(line):
1577 files.append(f)
1578 break
1579
1580 if len(files):
1581 return [output_api.PresubmitError(
1582 'Do not introduce new mojom targets with use_new_wrapper_types set to '
1583 'false. The mode is deprecated and will be removed soon.',
1584 files)]
1585 return []
1586
1587
jbriance9e12f162016-11-25 07:57:501588def _CheckUselessForwardDeclarations(input_api, output_api):
jbriance2c51e821a2016-12-12 08:24:311589 """Checks that added or removed lines in non third party affected
1590 header files do not lead to new useless class or struct forward
1591 declaration.
jbriance9e12f162016-11-25 07:57:501592 """
1593 results = []
1594 class_pattern = input_api.re.compile(r'^class\s+(\w+);$',
1595 input_api.re.MULTILINE)
1596 struct_pattern = input_api.re.compile(r'^struct\s+(\w+);$',
1597 input_api.re.MULTILINE)
1598 for f in input_api.AffectedFiles(include_deletes=False):
jbriance2c51e821a2016-12-12 08:24:311599 if (f.LocalPath().startswith('third_party') and
1600 not f.LocalPath().startswith('third_party/WebKit') and
1601 not f.LocalPath().startswith('third_party\\WebKit')):
1602 continue
1603
jbriance9e12f162016-11-25 07:57:501604 if not f.LocalPath().endswith('.h'):
1605 continue
1606
1607 contents = input_api.ReadFile(f)
1608 fwd_decls = input_api.re.findall(class_pattern, contents)
1609 fwd_decls.extend(input_api.re.findall(struct_pattern, contents))
1610
1611 useless_fwd_decls = []
1612 for decl in fwd_decls:
1613 count = sum(1 for _ in input_api.re.finditer(
1614 r'\b%s\b' % input_api.re.escape(decl), contents))
1615 if count == 1:
1616 useless_fwd_decls.append(decl)
1617
1618 if not useless_fwd_decls:
1619 continue
1620
1621 for line in f.GenerateScmDiff().splitlines():
1622 if (line.startswith('-') and not line.startswith('--') or
1623 line.startswith('+') and not line.startswith('++')):
1624 for decl in useless_fwd_decls:
1625 if input_api.re.search(r'\b%s\b' % decl, line[1:]):
1626 results.append(output_api.PresubmitPromptWarning(
1627 '%s: %s forward declaration is becoming useless' %
1628 (f.LocalPath(), decl)))
1629 useless_fwd_decls.remove(decl)
1630
1631 return results
1632
1633
dskiba88634f4e2015-08-14 23:03:291634def _CheckAndroidToastUsage(input_api, output_api):
1635 """Checks that code uses org.chromium.ui.widget.Toast instead of
1636 android.widget.Toast (Chromium Toast doesn't force hardware
1637 acceleration on low-end devices, saving memory).
1638 """
1639 toast_import_pattern = input_api.re.compile(
1640 r'^import android\.widget\.Toast;$')
1641
1642 errors = []
1643
1644 sources = lambda affected_file: input_api.FilterSourceFile(
1645 affected_file,
1646 black_list=(_EXCLUDED_PATHS +
1647 _TEST_CODE_EXCLUDED_PATHS +
1648 input_api.DEFAULT_BLACK_LIST +
1649 (r'^chromecast[\\\/].*',
1650 r'^remoting[\\\/].*')),
1651 white_list=(r'.*\.java$',))
1652
1653 for f in input_api.AffectedSourceFiles(sources):
1654 for line_num, line in f.ChangedContents():
1655 if toast_import_pattern.search(line):
1656 errors.append("%s:%d" % (f.LocalPath(), line_num))
1657
1658 results = []
1659
1660 if errors:
1661 results.append(output_api.PresubmitError(
1662 'android.widget.Toast usage is detected. Android toasts use hardware'
1663 ' acceleration, and can be\ncostly on low-end devices. Please use'
1664 ' org.chromium.ui.widget.Toast instead.\n'
1665 'Contact [email protected] if you have any questions.',
1666 errors))
1667
1668 return results
1669
1670
dgnaa68d5e2015-06-10 10:08:221671def _CheckAndroidCrLogUsage(input_api, output_api):
1672 """Checks that new logs using org.chromium.base.Log:
1673 - Are using 'TAG' as variable name for the tags (warn)
dgn38736db2015-09-18 19:20:511674 - Are using a tag that is shorter than 20 characters (error)
dgnaa68d5e2015-06-10 10:08:221675 """
pkotwicza1dd0b002016-05-16 14:41:041676
1677 # Do not check format of logs in //chrome/android/webapk because
1678 # //chrome/android/webapk cannot depend on //base
1679 cr_log_check_excluded_paths = [
1680 r"^chrome[\\\/]android[\\\/]webapk[\\\/].*",
1681 ]
1682
dgnaa68d5e2015-06-10 10:08:221683 cr_log_import_pattern = input_api.re.compile(
dgn87d9fb62015-06-12 09:15:121684 r'^import org\.chromium\.base\.Log;$', input_api.re.MULTILINE)
1685 class_in_base_pattern = input_api.re.compile(
1686 r'^package org\.chromium\.base;$', input_api.re.MULTILINE)
1687 has_some_log_import_pattern = input_api.re.compile(
1688 r'^import .*\.Log;$', input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221689 # Extract the tag from lines like `Log.d(TAG, "*");` or `Log.d("TAG", "*");`
dgn87d9fb62015-06-12 09:15:121690 log_call_pattern = input_api.re.compile(r'^\s*Log\.\w\((?P<tag>\"?\w+\"?)\,')
dgnaa68d5e2015-06-10 10:08:221691 log_decl_pattern = input_api.re.compile(
dgn38736db2015-09-18 19:20:511692 r'^\s*private static final String TAG = "(?P<name>(.*))";',
dgnaa68d5e2015-06-10 10:08:221693 input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221694
Vincent Scheib16d7b272015-09-15 18:09:071695 REF_MSG = ('See docs/android_logging.md '
dgnaa68d5e2015-06-10 10:08:221696 'or contact [email protected] for more info.')
pkotwicza1dd0b002016-05-16 14:41:041697 sources = lambda x: input_api.FilterSourceFile(x, white_list=(r'.*\.java$',),
1698 black_list=cr_log_check_excluded_paths)
dgn87d9fb62015-06-12 09:15:121699
dgnaa68d5e2015-06-10 10:08:221700 tag_decl_errors = []
1701 tag_length_errors = []
dgn87d9fb62015-06-12 09:15:121702 tag_errors = []
dgn38736db2015-09-18 19:20:511703 tag_with_dot_errors = []
dgn87d9fb62015-06-12 09:15:121704 util_log_errors = []
dgnaa68d5e2015-06-10 10:08:221705
1706 for f in input_api.AffectedSourceFiles(sources):
1707 file_content = input_api.ReadFile(f)
1708 has_modified_logs = False
1709
1710 # Per line checks
dgn87d9fb62015-06-12 09:15:121711 if (cr_log_import_pattern.search(file_content) or
1712 (class_in_base_pattern.search(file_content) and
1713 not has_some_log_import_pattern.search(file_content))):
1714 # Checks to run for files using cr log
dgnaa68d5e2015-06-10 10:08:221715 for line_num, line in f.ChangedContents():
1716
1717 # Check if the new line is doing some logging
dgn87d9fb62015-06-12 09:15:121718 match = log_call_pattern.search(line)
dgnaa68d5e2015-06-10 10:08:221719 if match:
1720 has_modified_logs = True
1721
1722 # Make sure it uses "TAG"
1723 if not match.group('tag') == 'TAG':
1724 tag_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgn87d9fb62015-06-12 09:15:121725 else:
1726 # Report non cr Log function calls in changed lines
1727 for line_num, line in f.ChangedContents():
1728 if log_call_pattern.search(line):
1729 util_log_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgnaa68d5e2015-06-10 10:08:221730
1731 # Per file checks
1732 if has_modified_logs:
1733 # Make sure the tag is using the "cr" prefix and is not too long
1734 match = log_decl_pattern.search(file_content)
dgn38736db2015-09-18 19:20:511735 tag_name = match.group('name') if match else None
1736 if not tag_name:
dgnaa68d5e2015-06-10 10:08:221737 tag_decl_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511738 elif len(tag_name) > 20:
dgnaa68d5e2015-06-10 10:08:221739 tag_length_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511740 elif '.' in tag_name:
1741 tag_with_dot_errors.append(f.LocalPath())
dgnaa68d5e2015-06-10 10:08:221742
1743 results = []
1744 if tag_decl_errors:
1745 results.append(output_api.PresubmitPromptWarning(
1746 'Please define your tags using the suggested format: .\n'
dgn38736db2015-09-18 19:20:511747 '"private static final String TAG = "<package tag>".\n'
1748 'They will be prepended with "cr_" automatically.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221749 tag_decl_errors))
1750
1751 if tag_length_errors:
1752 results.append(output_api.PresubmitError(
1753 'The tag length is restricted by the system to be at most '
dgn38736db2015-09-18 19:20:511754 '20 characters.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221755 tag_length_errors))
1756
1757 if tag_errors:
1758 results.append(output_api.PresubmitPromptWarning(
1759 'Please use a variable named "TAG" for your log tags.\n' + REF_MSG,
1760 tag_errors))
1761
dgn87d9fb62015-06-12 09:15:121762 if util_log_errors:
dgn4401aa52015-04-29 16:26:171763 results.append(output_api.PresubmitPromptWarning(
dgn87d9fb62015-06-12 09:15:121764 'Please use org.chromium.base.Log for new logs.\n' + REF_MSG,
1765 util_log_errors))
1766
dgn38736db2015-09-18 19:20:511767 if tag_with_dot_errors:
1768 results.append(output_api.PresubmitPromptWarning(
1769 'Dot in log tags cause them to be elided in crash reports.\n' + REF_MSG,
1770 tag_with_dot_errors))
1771
dgn4401aa52015-04-29 16:26:171772 return results
1773
1774
agrieve7b6479d82015-10-07 14:24:221775def _CheckAndroidNewMdpiAssetLocation(input_api, output_api):
1776 """Checks if MDPI assets are placed in a correct directory."""
1777 file_filter = lambda f: (f.LocalPath().endswith('.png') and
1778 ('/res/drawable/' in f.LocalPath() or
1779 '/res/drawable-ldrtl/' in f.LocalPath()))
1780 errors = []
1781 for f in input_api.AffectedFiles(include_deletes=False,
1782 file_filter=file_filter):
1783 errors.append(' %s' % f.LocalPath())
1784
1785 results = []
1786 if errors:
1787 results.append(output_api.PresubmitError(
1788 'MDPI assets should be placed in /res/drawable-mdpi/ or '
1789 '/res/drawable-ldrtl-mdpi/\ninstead of /res/drawable/ and'
1790 '/res/drawable-ldrtl/.\n'
1791 'Contact [email protected] if you have questions.', errors))
1792 return results
1793
1794
agrievef32bcc72016-04-04 14:57:401795class PydepsChecker(object):
1796 def __init__(self, input_api, pydeps_files):
1797 self._file_cache = {}
1798 self._input_api = input_api
1799 self._pydeps_files = pydeps_files
1800
1801 def _LoadFile(self, path):
1802 """Returns the list of paths within a .pydeps file relative to //."""
1803 if path not in self._file_cache:
1804 with open(path) as f:
1805 self._file_cache[path] = f.read()
1806 return self._file_cache[path]
1807
1808 def _ComputeNormalizedPydepsEntries(self, pydeps_path):
1809 """Returns an interable of paths within the .pydep, relativized to //."""
1810 os_path = self._input_api.os_path
1811 pydeps_dir = os_path.dirname(pydeps_path)
1812 entries = (l.rstrip() for l in self._LoadFile(pydeps_path).splitlines()
1813 if not l.startswith('*'))
1814 return (os_path.normpath(os_path.join(pydeps_dir, e)) for e in entries)
1815
1816 def _CreateFilesToPydepsMap(self):
1817 """Returns a map of local_path -> list_of_pydeps."""
1818 ret = {}
1819 for pydep_local_path in self._pydeps_files:
1820 for path in self._ComputeNormalizedPydepsEntries(pydep_local_path):
1821 ret.setdefault(path, []).append(pydep_local_path)
1822 return ret
1823
1824 def ComputeAffectedPydeps(self):
1825 """Returns an iterable of .pydeps files that might need regenerating."""
1826 affected_pydeps = set()
1827 file_to_pydeps_map = None
1828 for f in self._input_api.AffectedFiles(include_deletes=True):
1829 local_path = f.LocalPath()
1830 if local_path == 'DEPS':
1831 return self._pydeps_files
1832 elif local_path.endswith('.pydeps'):
1833 if local_path in self._pydeps_files:
1834 affected_pydeps.add(local_path)
1835 elif local_path.endswith('.py'):
1836 if file_to_pydeps_map is None:
1837 file_to_pydeps_map = self._CreateFilesToPydepsMap()
1838 affected_pydeps.update(file_to_pydeps_map.get(local_path, ()))
1839 return affected_pydeps
1840
1841 def DetermineIfStale(self, pydeps_path):
1842 """Runs print_python_deps.py to see if the files is stale."""
phajdan.jr0d9878552016-11-04 10:49:411843 import difflib
agrievef32bcc72016-04-04 14:57:401844 old_pydeps_data = self._LoadFile(pydeps_path).splitlines()
1845 cmd = old_pydeps_data[1][1:].strip()
1846 new_pydeps_data = self._input_api.subprocess.check_output(
1847 cmd + ' --output ""', shell=True)
phajdan.jr0d9878552016-11-04 10:49:411848 old_contents = old_pydeps_data[2:]
1849 new_contents = new_pydeps_data.splitlines()[2:]
agrievef32bcc72016-04-04 14:57:401850 if old_pydeps_data[2:] != new_pydeps_data.splitlines()[2:]:
phajdan.jr0d9878552016-11-04 10:49:411851 return cmd, '\n'.join(difflib.context_diff(old_contents, new_contents))
agrievef32bcc72016-04-04 14:57:401852
1853
1854def _CheckPydepsNeedsUpdating(input_api, output_api, checker_for_tests=None):
1855 """Checks if a .pydeps file needs to be regenerated."""
agrievebb9c5b472016-04-22 15:13:001856 # This check is mainly for Android, and involves paths not only in the
agrieve9bc4200b2016-05-04 16:33:281857 # PRESUBMIT.py, but also in the .pydeps files. It doesn't work on Windows and
1858 # Mac, so skip it on other platforms.
1859 if input_api.platform != 'linux2':
agrievebb9c5b472016-04-22 15:13:001860 return []
agrievef32bcc72016-04-04 14:57:401861 # TODO(agrieve): Update when there's a better way to detect this: crbug/570091
1862 is_android = input_api.os_path.exists('third_party/android_tools')
1863 pydeps_files = _ALL_PYDEPS_FILES if is_android else _GENERIC_PYDEPS_FILES
1864 results = []
1865 # First, check for new / deleted .pydeps.
1866 for f in input_api.AffectedFiles(include_deletes=True):
1867 if f.LocalPath().endswith('.pydeps'):
1868 if f.Action() == 'D' and f.LocalPath() in _ALL_PYDEPS_FILES:
1869 results.append(output_api.PresubmitError(
1870 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
1871 'remove %s' % f.LocalPath()))
1872 elif f.Action() != 'D' and f.LocalPath() not in _ALL_PYDEPS_FILES:
1873 results.append(output_api.PresubmitError(
1874 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
1875 'include %s' % f.LocalPath()))
1876
1877 if results:
1878 return results
1879
1880 checker = checker_for_tests or PydepsChecker(input_api, pydeps_files)
1881
1882 for pydep_path in checker.ComputeAffectedPydeps():
1883 try:
phajdan.jr0d9878552016-11-04 10:49:411884 result = checker.DetermineIfStale(pydep_path)
1885 if result:
1886 cmd, diff = result
agrievef32bcc72016-04-04 14:57:401887 results.append(output_api.PresubmitError(
phajdan.jr0d9878552016-11-04 10:49:411888 'File is stale: %s\nDiff (apply to fix):\n%s\n'
1889 'To regenerate, run:\n\n %s' %
1890 (pydep_path, diff, cmd)))
agrievef32bcc72016-04-04 14:57:401891 except input_api.subprocess.CalledProcessError as error:
1892 return [output_api.PresubmitError('Error running: %s' % error.cmd,
1893 long_text=error.output)]
1894
1895 return results
1896
1897
glidere61efad2015-02-18 17:39:431898def _CheckSingletonInHeaders(input_api, output_api):
1899 """Checks to make sure no header files have |Singleton<|."""
1900 def FileFilter(affected_file):
1901 # It's ok for base/memory/singleton.h to have |Singleton<|.
1902 black_list = (_EXCLUDED_PATHS +
1903 input_api.DEFAULT_BLACK_LIST +
1904 (r"^base[\\\/]memory[\\\/]singleton\.h$",))
1905 return input_api.FilterSourceFile(affected_file, black_list=black_list)
1906
sergeyu34d21222015-09-16 00:11:441907 pattern = input_api.re.compile(r'(?<!class\sbase::)Singleton\s*<')
glidere61efad2015-02-18 17:39:431908 files = []
1909 for f in input_api.AffectedSourceFiles(FileFilter):
1910 if (f.LocalPath().endswith('.h') or f.LocalPath().endswith('.hxx') or
1911 f.LocalPath().endswith('.hpp') or f.LocalPath().endswith('.inl')):
1912 contents = input_api.ReadFile(f)
1913 for line in contents.splitlines(False):
oysteinec430ad42015-10-22 20:55:241914 if (not line.lstrip().startswith('//') and # Strip C++ comment.
glidere61efad2015-02-18 17:39:431915 pattern.search(line)):
1916 files.append(f)
1917 break
1918
1919 if files:
yolandyandaabc6d2016-04-18 18:29:391920 return [output_api.PresubmitError(
sergeyu34d21222015-09-16 00:11:441921 'Found base::Singleton<T> in the following header files.\n' +
glidere61efad2015-02-18 17:39:431922 'Please move them to an appropriate source file so that the ' +
1923 'template gets instantiated in a single compilation unit.',
1924 files) ]
1925 return []
1926
1927
dbeam1ec68ac2016-12-15 05:22:241928def _CheckNoDeprecatedCompiledResourcesGyp(input_api, output_api):
dbeam37e8e7402016-02-10 22:58:201929 """Checks for old style compiled_resources.gyp files."""
1930 is_compiled_resource = lambda fp: fp.endswith('compiled_resources.gyp')
1931
1932 added_compiled_resources = filter(is_compiled_resource, [
1933 f.LocalPath() for f in input_api.AffectedFiles() if f.Action() == 'A'
1934 ])
1935
1936 if not added_compiled_resources:
1937 return []
1938
1939 return [output_api.PresubmitError(
1940 "Found new compiled_resources.gyp files:\n%s\n\n"
1941 "compiled_resources.gyp files are deprecated,\n"
michaelpgdb9985072016-02-24 19:13:551942 "please use compiled_resources2.gyp instead:\n"
1943 "https://chromium.googlesource.com/chromium/src/+/master/docs/closure_compilation.md"
1944 %
dbeam37e8e7402016-02-10 22:58:201945 "\n".join(added_compiled_resources))]
1946
1947
[email protected]fd20b902014-05-09 02:14:531948_DEPRECATED_CSS = [
1949 # Values
1950 ( "-webkit-box", "flex" ),
1951 ( "-webkit-inline-box", "inline-flex" ),
1952 ( "-webkit-flex", "flex" ),
1953 ( "-webkit-inline-flex", "inline-flex" ),
1954 ( "-webkit-min-content", "min-content" ),
1955 ( "-webkit-max-content", "max-content" ),
1956
1957 # Properties
1958 ( "-webkit-background-clip", "background-clip" ),
1959 ( "-webkit-background-origin", "background-origin" ),
1960 ( "-webkit-background-size", "background-size" ),
1961 ( "-webkit-box-shadow", "box-shadow" ),
1962
1963 # Functions
1964 ( "-webkit-gradient", "gradient" ),
1965 ( "-webkit-repeating-gradient", "repeating-gradient" ),
1966 ( "-webkit-linear-gradient", "linear-gradient" ),
1967 ( "-webkit-repeating-linear-gradient", "repeating-linear-gradient" ),
1968 ( "-webkit-radial-gradient", "radial-gradient" ),
1969 ( "-webkit-repeating-radial-gradient", "repeating-radial-gradient" ),
1970]
1971
dbeam1ec68ac2016-12-15 05:22:241972def _CheckNoDeprecatedCss(input_api, output_api):
[email protected]fd20b902014-05-09 02:14:531973 """ Make sure that we don't use deprecated CSS
[email protected]9a48e3f82014-05-22 00:06:251974 properties, functions or values. Our external
mdjonesae0286c32015-06-10 18:10:341975 documentation and iOS CSS for dom distiller
1976 (reader mode) are ignored by the hooks as it
[email protected]9a48e3f82014-05-22 00:06:251977 needs to be consumed by WebKit. """
[email protected]fd20b902014-05-09 02:14:531978 results = []
dbeam070cfe62014-10-22 06:44:021979 file_inclusion_pattern = (r".+\.css$",)
[email protected]9a48e3f82014-05-22 00:06:251980 black_list = (_EXCLUDED_PATHS +
1981 _TEST_CODE_EXCLUDED_PATHS +
1982 input_api.DEFAULT_BLACK_LIST +
1983 (r"^chrome/common/extensions/docs",
1984 r"^chrome/docs",
mdjonesae0286c32015-06-10 18:10:341985 r"^components/dom_distiller/core/css/distilledpage_ios.css",
sdefresneda218472015-12-07 18:38:051986 r"^components/flags_ui/resources/apple_flags.css",
sdefresne6308d7f2016-02-15 09:38:441987 r"^components/neterror/resources/neterror.css",
[email protected]9a48e3f82014-05-22 00:06:251988 r"^native_client_sdk"))
1989 file_filter = lambda f: input_api.FilterSourceFile(
1990 f, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]fd20b902014-05-09 02:14:531991 for fpath in input_api.AffectedFiles(file_filter=file_filter):
1992 for line_num, line in fpath.ChangedContents():
1993 for (deprecated_value, value) in _DEPRECATED_CSS:
dbeam070cfe62014-10-22 06:44:021994 if deprecated_value in line:
[email protected]fd20b902014-05-09 02:14:531995 results.append(output_api.PresubmitError(
1996 "%s:%d: Use of deprecated CSS %s, use %s instead" %
1997 (fpath.LocalPath(), line_num, deprecated_value, value)))
1998 return results
1999
mohan.reddyf21db962014-10-16 12:26:472000
dbeam070cfe62014-10-22 06:44:022001_DEPRECATED_JS = [
2002 ( "__lookupGetter__", "Object.getOwnPropertyDescriptor" ),
2003 ( "__defineGetter__", "Object.defineProperty" ),
2004 ( "__defineSetter__", "Object.defineProperty" ),
2005]
2006
dbeam1ec68ac2016-12-15 05:22:242007def _CheckNoDeprecatedJs(input_api, output_api):
dbeam070cfe62014-10-22 06:44:022008 """Make sure that we don't use deprecated JS in Chrome code."""
2009 results = []
2010 file_inclusion_pattern = (r".+\.js$",) # TODO(dbeam): .html?
2011 black_list = (_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
2012 input_api.DEFAULT_BLACK_LIST)
2013 file_filter = lambda f: input_api.FilterSourceFile(
2014 f, white_list=file_inclusion_pattern, black_list=black_list)
2015 for fpath in input_api.AffectedFiles(file_filter=file_filter):
2016 for lnum, line in fpath.ChangedContents():
2017 for (deprecated, replacement) in _DEPRECATED_JS:
2018 if deprecated in line:
2019 results.append(output_api.PresubmitError(
2020 "%s:%d: Use of deprecated JS %s, use %s instead" %
2021 (fpath.LocalPath(), lnum, deprecated, replacement)))
2022 return results
2023
2024
dbeam1ec68ac2016-12-15 05:22:242025def _CheckForRiskyJsFeatures(input_api, output_api):
2026 maybe_ios_js = (r"^(ios|components|ui\/webui\/resources)\/.+\.js$", )
2027 file_filter = lambda f: input_api.FilterSourceFile(f, white_list=maybe_ios_js)
2028
2029 arrow_lines = []
2030 for f in input_api.AffectedFiles(file_filter=file_filter):
2031 for lnum, line in f.ChangedContents():
2032 if ' => ' in line:
2033 arrow_lines.append((f.LocalPath(), lnum))
2034
2035 if not arrow_lines:
2036 return []
2037
2038 return [output_api.PresubmitPromptWarning("""
2039Use of => operator detected in:
2040%s
2041Please ensure your code does not run on iOS9 (=> (arrow) does not work there).
2042https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#Arrow-Functions
2043""" % "\n".join(" %s:%d\n" % line for line in arrow_lines))]
2044
2045
dgnaa68d5e2015-06-10 10:08:222046def _AndroidSpecificOnUploadChecks(input_api, output_api):
2047 """Groups checks that target android code."""
2048 results = []
dgnaa68d5e2015-06-10 10:08:222049 results.extend(_CheckAndroidCrLogUsage(input_api, output_api))
agrieve7b6479d82015-10-07 14:24:222050 results.extend(_CheckAndroidNewMdpiAssetLocation(input_api, output_api))
dskiba88634f4e2015-08-14 23:03:292051 results.extend(_CheckAndroidToastUsage(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:222052 return results
2053
2054
[email protected]22c9bd72011-03-27 16:47:392055def _CommonChecks(input_api, output_api):
2056 """Checks common to both upload and commit."""
2057 results = []
2058 results.extend(input_api.canned_checks.PanProjectChecks(
[email protected]3de922f2013-12-20 13:27:382059 input_api, output_api,
2060 excluded_paths=_EXCLUDED_PATHS + _TESTRUNNER_PATHS))
machenbachfbda9b72016-12-06 13:13:582061 results.extend(
2062 input_api.canned_checks.CheckAuthorizedAuthor(input_api, output_api))
[email protected]55459852011-08-10 15:17:192063 results.extend(
[email protected]760deea2013-12-10 19:33:492064 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api))
[email protected]10689ca2011-09-02 02:31:542065 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
[email protected]72df4e782012-06-21 16:28:182066 results.extend(_CheckNoUNIT_TESTInSourceFiles(input_api, output_api))
danakj61c1aa22015-10-26 19:55:522067 results.extend(_CheckDCHECK_IS_ONHasBraces(input_api, output_api))
[email protected]8ea5d4b2011-09-13 21:49:222068 results.extend(_CheckNoNewWStrings(input_api, output_api))
[email protected]2a8ac9c2011-10-19 17:20:442069 results.extend(_CheckNoDEPSGIT(input_api, output_api))
[email protected]127f18ec2012-06-16 05:05:592070 results.extend(_CheckNoBannedFunctions(input_api, output_api))
[email protected]6c063c62012-07-11 19:11:062071 results.extend(_CheckNoPragmaOnce(input_api, output_api))
[email protected]e7479052012-09-19 00:26:122072 results.extend(_CheckNoTrinaryTrueFalse(input_api, output_api))
[email protected]55f9f382012-07-31 11:02:182073 results.extend(_CheckUnwantedDependencies(input_api, output_api))
[email protected]fbcafe5a2012-08-08 15:31:222074 results.extend(_CheckFilePermissions(input_api, output_api))
[email protected]c8278b32012-10-30 20:35:492075 results.extend(_CheckNoAuraWindowPropertyHInHeaders(input_api, output_api))
[email protected]2309b0fa02012-11-16 12:18:272076 results.extend(_CheckIncludeOrder(input_api, output_api))
[email protected]70ca77752012-11-20 03:45:032077 results.extend(_CheckForVersionControlConflicts(input_api, output_api))
[email protected]b8079ae4a2012-12-05 19:56:492078 results.extend(_CheckPatchFiles(input_api, output_api))
[email protected]06e6d0ff2012-12-11 01:36:442079 results.extend(_CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api))
[email protected]d2530012013-01-25 16:39:272080 results.extend(_CheckNoAbbreviationInPngFileName(input_api, output_api))
[email protected]b00342e7f2013-03-26 16:21:542081 results.extend(_CheckForInvalidOSMacros(input_api, output_api))
lliabraa35bab3932014-10-01 12:16:442082 results.extend(_CheckForInvalidIfDefinedMacros(input_api, output_api))
yolandyandaabc6d2016-04-18 18:29:392083 results.extend(_CheckFlakyTestUsage(input_api, output_api))
[email protected]e871964c2013-05-13 14:14:552084 results.extend(_CheckAddedDepsHaveTargetApprovals(input_api, output_api))
[email protected]9f919cc2013-07-31 03:04:042085 results.extend(
2086 input_api.canned_checks.CheckChangeHasNoTabs(
2087 input_api,
2088 output_api,
2089 source_file_filter=lambda x: x.LocalPath().endswith('.grd')))
[email protected]85218562013-11-22 07:41:402090 results.extend(_CheckSpamLogging(input_api, output_api))
[email protected]49aa76a2013-12-04 06:59:162091 results.extend(_CheckForAnonymousVariables(input_api, output_api))
[email protected]5fe0f8742013-11-29 01:04:592092 results.extend(_CheckCygwinShell(input_api, output_api))
[email protected]999261d2014-03-03 20:08:082093 results.extend(_CheckUserActionUpdate(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:242094 results.extend(_CheckNoDeprecatedCss(input_api, output_api))
2095 results.extend(_CheckNoDeprecatedJs(input_api, output_api))
[email protected]99171a92014-06-03 08:44:472096 results.extend(_CheckParseErrors(input_api, output_api))
mlamouria82272622014-09-16 18:45:042097 results.extend(_CheckForIPCRules(input_api, output_api))
mostynbb639aca52015-01-07 20:31:232098 results.extend(_CheckForWindowsLineEndings(input_api, output_api))
glidere61efad2015-02-18 17:39:432099 results.extend(_CheckSingletonInHeaders(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:242100 results.extend(_CheckNoDeprecatedCompiledResourcesGyp(input_api, output_api))
agrievef32bcc72016-04-04 14:57:402101 results.extend(_CheckPydepsNeedsUpdating(input_api, output_api))
wnwenbdc444e2016-05-25 13:44:152102 results.extend(_CheckJavaStyle(input_api, output_api))
dchenge07de812016-06-20 19:27:172103 results.extend(_CheckIpcOwners(input_api, output_api))
yzshend99f726a2016-07-25 21:44:232104 results.extend(_CheckMojoUsesNewWrapperTypes(input_api, output_api))
jbriance9e12f162016-11-25 07:57:502105 results.extend(_CheckUselessForwardDeclarations(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:242106 results.extend(_CheckForRiskyJsFeatures(input_api, output_api))
[email protected]2299dcf2012-11-15 19:56:242107
2108 if any('PRESUBMIT.py' == f.LocalPath() for f in input_api.AffectedFiles()):
2109 results.extend(input_api.canned_checks.RunUnitTestsInDirectory(
2110 input_api, output_api,
2111 input_api.PresubmitLocalPath(),
[email protected]6be63382013-01-21 15:42:382112 whitelist=[r'^PRESUBMIT_test\.py$']))
[email protected]22c9bd72011-03-27 16:47:392113 return results
[email protected]1f7b4172010-01-28 01:17:342114
[email protected]b337cb5b2011-01-23 21:24:052115
[email protected]b8079ae4a2012-12-05 19:56:492116def _CheckPatchFiles(input_api, output_api):
2117 problems = [f.LocalPath() for f in input_api.AffectedFiles()
2118 if f.LocalPath().endswith(('.orig', '.rej'))]
2119 if problems:
2120 return [output_api.PresubmitError(
2121 "Don't commit .rej and .orig files.", problems)]
[email protected]2fdd1f362013-01-16 03:56:032122 else:
2123 return []
[email protected]b8079ae4a2012-12-05 19:56:492124
2125
[email protected]b00342e7f2013-03-26 16:21:542126def _DidYouMeanOSMacro(bad_macro):
2127 try:
2128 return {'A': 'OS_ANDROID',
2129 'B': 'OS_BSD',
2130 'C': 'OS_CHROMEOS',
2131 'F': 'OS_FREEBSD',
2132 'L': 'OS_LINUX',
2133 'M': 'OS_MACOSX',
2134 'N': 'OS_NACL',
2135 'O': 'OS_OPENBSD',
2136 'P': 'OS_POSIX',
2137 'S': 'OS_SOLARIS',
2138 'W': 'OS_WIN'}[bad_macro[3].upper()]
2139 except KeyError:
2140 return ''
2141
2142
2143def _CheckForInvalidOSMacrosInFile(input_api, f):
2144 """Check for sensible looking, totally invalid OS macros."""
2145 preprocessor_statement = input_api.re.compile(r'^\s*#')
2146 os_macro = input_api.re.compile(r'defined\((OS_[^)]+)\)')
2147 results = []
2148 for lnum, line in f.ChangedContents():
2149 if preprocessor_statement.search(line):
2150 for match in os_macro.finditer(line):
2151 if not match.group(1) in _VALID_OS_MACROS:
2152 good = _DidYouMeanOSMacro(match.group(1))
2153 did_you_mean = ' (did you mean %s?)' % good if good else ''
2154 results.append(' %s:%d %s%s' % (f.LocalPath(),
2155 lnum,
2156 match.group(1),
2157 did_you_mean))
2158 return results
2159
2160
2161def _CheckForInvalidOSMacros(input_api, output_api):
2162 """Check all affected files for invalid OS macros."""
2163 bad_macros = []
2164 for f in input_api.AffectedFiles():
ellyjones47654342016-05-06 15:50:472165 if not f.LocalPath().endswith(('.py', '.js', '.html', '.css', '.md')):
[email protected]b00342e7f2013-03-26 16:21:542166 bad_macros.extend(_CheckForInvalidOSMacrosInFile(input_api, f))
2167
2168 if not bad_macros:
2169 return []
2170
2171 return [output_api.PresubmitError(
2172 'Possibly invalid OS macro[s] found. Please fix your code\n'
2173 'or add your macro to src/PRESUBMIT.py.', bad_macros)]
2174
lliabraa35bab3932014-10-01 12:16:442175
2176def _CheckForInvalidIfDefinedMacrosInFile(input_api, f):
2177 """Check all affected files for invalid "if defined" macros."""
2178 ALWAYS_DEFINED_MACROS = (
2179 "TARGET_CPU_PPC",
2180 "TARGET_CPU_PPC64",
2181 "TARGET_CPU_68K",
2182 "TARGET_CPU_X86",
2183 "TARGET_CPU_ARM",
2184 "TARGET_CPU_MIPS",
2185 "TARGET_CPU_SPARC",
2186 "TARGET_CPU_ALPHA",
2187 "TARGET_IPHONE_SIMULATOR",
2188 "TARGET_OS_EMBEDDED",
2189 "TARGET_OS_IPHONE",
2190 "TARGET_OS_MAC",
2191 "TARGET_OS_UNIX",
2192 "TARGET_OS_WIN32",
2193 )
2194 ifdef_macro = input_api.re.compile(r'^\s*#.*(?:ifdef\s|defined\()([^\s\)]+)')
2195 results = []
2196 for lnum, line in f.ChangedContents():
2197 for match in ifdef_macro.finditer(line):
2198 if match.group(1) in ALWAYS_DEFINED_MACROS:
2199 always_defined = ' %s is always defined. ' % match.group(1)
2200 did_you_mean = 'Did you mean \'#if %s\'?' % match.group(1)
2201 results.append(' %s:%d %s\n\t%s' % (f.LocalPath(),
2202 lnum,
2203 always_defined,
2204 did_you_mean))
2205 return results
2206
2207
2208def _CheckForInvalidIfDefinedMacros(input_api, output_api):
2209 """Check all affected files for invalid "if defined" macros."""
2210 bad_macros = []
2211 for f in input_api.AffectedFiles():
2212 if f.LocalPath().endswith(('.h', '.c', '.cc', '.m', '.mm')):
2213 bad_macros.extend(_CheckForInvalidIfDefinedMacrosInFile(input_api, f))
2214
2215 if not bad_macros:
2216 return []
2217
2218 return [output_api.PresubmitError(
2219 'Found ifdef check on always-defined macro[s]. Please fix your code\n'
2220 'or check the list of ALWAYS_DEFINED_MACROS in src/PRESUBMIT.py.',
2221 bad_macros)]
2222
2223
mlamouria82272622014-09-16 18:45:042224def _CheckForIPCRules(input_api, output_api):
2225 """Check for same IPC rules described in
2226 http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc
2227 """
2228 base_pattern = r'IPC_ENUM_TRAITS\('
2229 inclusion_pattern = input_api.re.compile(r'(%s)' % base_pattern)
2230 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_pattern)
2231
2232 problems = []
2233 for f in input_api.AffectedSourceFiles(None):
2234 local_path = f.LocalPath()
2235 if not local_path.endswith('.h'):
2236 continue
2237 for line_number, line in f.ChangedContents():
2238 if inclusion_pattern.search(line) and not comment_pattern.search(line):
2239 problems.append(
2240 '%s:%d\n %s' % (local_path, line_number, line.strip()))
2241
2242 if problems:
2243 return [output_api.PresubmitPromptWarning(
2244 _IPC_ENUM_TRAITS_DEPRECATED, problems)]
2245 else:
2246 return []
2247
[email protected]b00342e7f2013-03-26 16:21:542248
mostynbb639aca52015-01-07 20:31:232249def _CheckForWindowsLineEndings(input_api, output_api):
2250 """Check source code and known ascii text files for Windows style line
2251 endings.
2252 """
earthdok1b5e0ee2015-03-10 15:19:102253 known_text_files = r'.*\.(txt|html|htm|mhtml|py|gyp|gypi|gn|isolate)$'
mostynbb639aca52015-01-07 20:31:232254
2255 file_inclusion_pattern = (
2256 known_text_files,
2257 r'.+%s' % _IMPLEMENTATION_EXTENSIONS
2258 )
2259
2260 filter = lambda f: input_api.FilterSourceFile(
2261 f, white_list=file_inclusion_pattern, black_list=None)
2262 files = [f.LocalPath() for f in
2263 input_api.AffectedSourceFiles(filter)]
2264
2265 problems = []
2266
2267 for file in files:
2268 fp = open(file, 'r')
2269 for line in fp:
2270 if line.endswith('\r\n'):
2271 problems.append(file)
2272 break
2273 fp.close()
2274
2275 if problems:
2276 return [output_api.PresubmitPromptWarning('Are you sure that you want '
2277 'these files to contain Windows style line endings?\n' +
2278 '\n'.join(problems))]
2279
2280 return []
2281
2282
pastarmovj89f7ee12016-09-20 14:58:132283def _CheckSyslogUseWarning(input_api, output_api, source_file_filter=None,
2284 lint_filters=None, verbose_level=None):
2285 """Checks that all source files use SYSLOG properly."""
2286 syslog_files = []
2287 for f in input_api.AffectedSourceFiles(source_file_filter):
2288 if 'SYSLOG' in input_api.ReadFile(f, 'rb'):
2289 syslog_files.append(f.LocalPath())
2290 if syslog_files:
2291 return [output_api.PresubmitPromptWarning(
2292 'Please make sure there are no privacy sensitive bits of data in SYSLOG'
2293 ' calls.\nFiles to check:\n', items=syslog_files)]
2294 return []
2295
2296
[email protected]1f7b4172010-01-28 01:17:342297def CheckChangeOnUpload(input_api, output_api):
2298 results = []
2299 results.extend(_CommonChecks(input_api, output_api))
tandriief664692014-09-23 14:51:472300 results.extend(_CheckValidHostsInDEPS(input_api, output_api))
scottmg39b29952014-12-08 18:31:282301 results.extend(
2302 input_api.canned_checks.CheckGNFormatted(input_api, output_api))
mcasasb7440c282015-02-04 14:52:192303 results.extend(_CheckUmaHistogramChanges(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:222304 results.extend(_AndroidSpecificOnUploadChecks(input_api, output_api))
pastarmovj89f7ee12016-09-20 14:58:132305 results.extend(_CheckSyslogUseWarning(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542306 return results
[email protected]ca8d19842009-02-19 16:33:122307
2308
[email protected]1bfb8322014-04-23 01:02:412309def GetTryServerMasterForBot(bot):
2310 """Returns the Try Server master for the given bot.
2311
[email protected]0bb112362014-07-26 04:38:322312 It tries to guess the master from the bot name, but may still fail
2313 and return None. There is no longer a default master.
2314 """
2315 # Potentially ambiguous bot names are listed explicitly.
2316 master_map = {
tandriie5587792016-07-14 00:34:502317 'chromium_presubmit': 'master.tryserver.chromium.linux',
2318 'tools_build_presubmit': 'master.tryserver.chromium.linux',
[email protected]1bfb8322014-04-23 01:02:412319 }
[email protected]0bb112362014-07-26 04:38:322320 master = master_map.get(bot)
2321 if not master:
wnwen4fbaab82016-05-25 12:54:362322 if 'android' in bot:
tandriie5587792016-07-14 00:34:502323 master = 'master.tryserver.chromium.android'
wnwen4fbaab82016-05-25 12:54:362324 elif 'linux' in bot or 'presubmit' in bot:
tandriie5587792016-07-14 00:34:502325 master = 'master.tryserver.chromium.linux'
[email protected]0bb112362014-07-26 04:38:322326 elif 'win' in bot:
tandriie5587792016-07-14 00:34:502327 master = 'master.tryserver.chromium.win'
[email protected]0bb112362014-07-26 04:38:322328 elif 'mac' in bot or 'ios' in bot:
tandriie5587792016-07-14 00:34:502329 master = 'master.tryserver.chromium.mac'
[email protected]0bb112362014-07-26 04:38:322330 return master
[email protected]1bfb8322014-04-23 01:02:412331
2332
Paweł Hajdan, Jr55083782014-12-19 20:32:562333def GetDefaultTryConfigs(bots):
2334 """Returns a list of ('bot', set(['tests']), filtered by [bots].
[email protected]38c6a512013-12-18 23:48:012335 """
2336
Paweł Hajdan, Jr55083782014-12-19 20:32:562337 builders_and_tests = dict((bot, set(['defaulttests'])) for bot in bots)
[email protected]1bfb8322014-04-23 01:02:412338
2339 # Build up the mapping from tryserver master to bot/test.
2340 out = dict()
Paweł Hajdan, Jr55083782014-12-19 20:32:562341 for bot, tests in builders_and_tests.iteritems():
[email protected]1bfb8322014-04-23 01:02:412342 out.setdefault(GetTryServerMasterForBot(bot), {})[bot] = tests
2343 return out
[email protected]38c6a512013-12-18 23:48:012344
2345
[email protected]ca8d19842009-02-19 16:33:122346def CheckChangeOnCommit(input_api, output_api):
[email protected]fe5f57c52009-06-05 14:25:542347 results = []
[email protected]1f7b4172010-01-28 01:17:342348 results.extend(_CommonChecks(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542349 # Make sure the tree is 'open'.
[email protected]806e98e2010-03-19 17:49:272350 results.extend(input_api.canned_checks.CheckTreeIsOpen(
[email protected]7f238152009-08-12 19:00:342351 input_api,
2352 output_api,
[email protected]2fdd1f362013-01-16 03:56:032353 json_url='http://chromium-status.appspot.com/current?format=json'))
[email protected]806e98e2010-03-19 17:49:272354
[email protected]3e4eb112011-01-18 03:29:542355 results.extend(input_api.canned_checks.CheckChangeHasBugField(
2356 input_api, output_api))
[email protected]c4b47562011-12-05 23:39:412357 results.extend(input_api.canned_checks.CheckChangeHasDescription(
2358 input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542359 return results