blob: 5fca8c1ad302868ca796ffc0fa652cd1b1f64fa8 [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
[email protected]06e6d0ff2012-12-11 01:36:4431# Fragment of a regular expression that matches C++ and Objective-C++
32# implementation files.
33_IMPLEMENTATION_EXTENSIONS = r'\.(cc|cpp|cxx|mm)$'
34
wnwenbdc444e2016-05-25 13:44:1535
[email protected]06e6d0ff2012-12-11 01:36:4436# Regular expression that matches code only used for test binaries
37# (best effort).
38_TEST_CODE_EXCLUDED_PATHS = (
joaodasilva718f87672014-08-30 09:25:4939 r'.*[\\\/](fake_|test_|mock_).+%s' % _IMPLEMENTATION_EXTENSIONS,
[email protected]06e6d0ff2012-12-11 01:36:4440 r'.+_test_(base|support|util)%s' % _IMPLEMENTATION_EXTENSIONS,
sdefresne1fccb0a2016-12-19 08:10:5341 r'.+_(api|browser|eg|perf|pixel|unit|ui)?test(_[a-z]+)?%s' %
[email protected]e2d7e6f2013-04-23 12:57:1242 _IMPLEMENTATION_EXTENSIONS,
[email protected]06e6d0ff2012-12-11 01:36:4443 r'.+profile_sync_service_harness%s' % _IMPLEMENTATION_EXTENSIONS,
joaodasilva718f87672014-08-30 09:25:4944 r'.*[\\\/](test|tool(s)?)[\\\/].*',
[email protected]ef070cc2013-05-03 11:53:0545 # content_shell is used for running layout tests.
joaodasilva718f87672014-08-30 09:25:4946 r'content[\\\/]shell[\\\/].*',
[email protected]7b054982013-11-27 00:44:4747 # Non-production example code.
joaodasilva718f87672014-08-30 09:25:4948 r'mojo[\\\/]examples[\\\/].*',
[email protected]8176de12014-06-20 19:07:0849 # Launcher for running iOS tests on the simulator.
joaodasilva718f87672014-08-30 09:25:4950 r'testing[\\\/]iossim[\\\/]iossim\.mm$',
[email protected]06e6d0ff2012-12-11 01:36:4451)
[email protected]ca8d19842009-02-19 16:33:1252
wnwenbdc444e2016-05-25 13:44:1553
[email protected]eea609a2011-11-18 13:10:1254_TEST_ONLY_WARNING = (
55 'You might be calling functions intended only for testing from\n'
56 'production code. It is OK to ignore this warning if you know what\n'
57 'you are doing, as the heuristics used to detect the situation are\n'
[email protected]b0149772014-03-27 16:47:5858 'not perfect. The commit queue will not block on this warning.')
[email protected]eea609a2011-11-18 13:10:1259
60
[email protected]cf9b78f2012-11-14 11:40:2861_INCLUDE_ORDER_WARNING = (
marjaa017dc482015-03-09 17:13:4062 'Your #include order seems to be broken. Remember to use the right '
avice9a8982015-11-24 20:36:2163 'collation (LC_COLLATE=C) and check\nhttps://google.github.io/styleguide/'
64 'cppguide.html#Names_and_Order_of_Includes')
[email protected]cf9b78f2012-11-14 11:40:2865
wnwenbdc444e2016-05-25 13:44:1566
[email protected]127f18ec2012-06-16 05:05:5967_BANNED_OBJC_FUNCTIONS = (
68 (
69 'addTrackingRect:',
[email protected]23e6cbc2012-06-16 18:51:2070 (
71 'The use of -[NSView addTrackingRect:owner:userData:assumeInside:] is'
[email protected]127f18ec2012-06-16 05:05:5972 'prohibited. Please use CrTrackingArea instead.',
73 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
74 ),
75 False,
76 ),
77 (
[email protected]eaae1972014-04-16 04:17:2678 r'/NSTrackingArea\W',
[email protected]23e6cbc2012-06-16 18:51:2079 (
80 'The use of NSTrackingAreas is prohibited. Please use CrTrackingArea',
[email protected]127f18ec2012-06-16 05:05:5981 'instead.',
82 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
83 ),
84 False,
85 ),
86 (
87 'convertPointFromBase:',
[email protected]23e6cbc2012-06-16 18:51:2088 (
89 'The use of -[NSView convertPointFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:5990 'Please use |convertPoint:(point) fromView:nil| instead.',
91 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
92 ),
93 True,
94 ),
95 (
96 'convertPointToBase:',
[email protected]23e6cbc2012-06-16 18:51:2097 (
98 'The use of -[NSView convertPointToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:5999 'Please use |convertPoint:(point) toView:nil| instead.',
100 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
101 ),
102 True,
103 ),
104 (
105 'convertRectFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20106 (
107 'The use of -[NSView convertRectFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59108 'Please use |convertRect:(point) fromView:nil| instead.',
109 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
110 ),
111 True,
112 ),
113 (
114 'convertRectToBase:',
[email protected]23e6cbc2012-06-16 18:51:20115 (
116 'The use of -[NSView convertRectToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59117 'Please use |convertRect:(point) toView:nil| instead.',
118 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
119 ),
120 True,
121 ),
122 (
123 'convertSizeFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20124 (
125 'The use of -[NSView convertSizeFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59126 'Please use |convertSize:(point) fromView:nil| instead.',
127 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
128 ),
129 True,
130 ),
131 (
132 'convertSizeToBase:',
[email protected]23e6cbc2012-06-16 18:51:20133 (
134 'The use of -[NSView convertSizeToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59135 'Please use |convertSize:(point) toView:nil| instead.',
136 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
137 ),
138 True,
139 ),
jif65398702016-10-27 10:19:48140 (
141 r"/\s+UTF8String\s*]",
142 (
143 'The use of -[NSString UTF8String] is dangerous as it can return null',
144 'even if |canBeConvertedToEncoding:NSUTF8StringEncoding| returns YES.',
145 'Please use |SysNSStringToUTF8| instead.',
146 ),
147 True,
148 ),
[email protected]127f18ec2012-06-16 05:05:59149)
150
151
152_BANNED_CPP_FUNCTIONS = (
[email protected]23e6cbc2012-06-16 18:51:20153 # Make sure that gtest's FRIEND_TEST() macro is not used; the
154 # FRIEND_TEST_ALL_PREFIXES() macro from base/gtest_prod_util.h should be
[email protected]e00ccc92012-11-01 17:32:30155 # used instead since that allows for FLAKY_ and DISABLED_ prefixes.
[email protected]23e6cbc2012-06-16 18:51:20156 (
157 'FRIEND_TEST(',
158 (
[email protected]e3c945502012-06-26 20:01:49159 'Chromium code should not use gtest\'s FRIEND_TEST() macro. Include',
[email protected]23e6cbc2012-06-16 18:51:20160 'base/gtest_prod_util.h and use FRIEND_TEST_ALL_PREFIXES() instead.',
161 ),
162 False,
[email protected]7345da02012-11-27 14:31:49163 (),
[email protected]23e6cbc2012-06-16 18:51:20164 ),
165 (
thomasanderson4b569052016-09-14 20:15:53166 r'XSelectInput|CWEventMask|XCB_CW_EVENT_MASK',
167 (
168 'Chrome clients wishing to select events on X windows should use',
169 'ui::XScopedEventSelector. It is safe to ignore this warning only if',
170 'you are selecting events from the GPU process, or if you are using',
171 'an XDisplay other than gfx::GetXDisplay().',
172 ),
173 True,
174 (
175 r"^ui[\\\/]gl[\\\/].*\.cc$",
176 r"^media[\\\/]gpu[\\\/].*\.cc$",
177 r"^gpu[\\\/].*\.cc$",
178 ),
179 ),
180 (
[email protected]23e6cbc2012-06-16 18:51:20181 'ScopedAllowIO',
182 (
[email protected]e3c945502012-06-26 20:01:49183 'New code should not use ScopedAllowIO. Post a task to the blocking',
184 'pool or the FILE thread instead.',
[email protected]23e6cbc2012-06-16 18:51:20185 ),
[email protected]e3c945502012-06-26 20:01:49186 True,
[email protected]7345da02012-11-27 14:31:49187 (
nyad2c548b2015-12-09 03:22:32188 r"^base[\\\/]process[\\\/]process_linux\.cc$",
thestig75844fdb2014-09-09 19:47:10189 r"^base[\\\/]process[\\\/]process_metrics_linux\.cc$",
kmarshallbb619532016-01-29 21:24:49190 r"^blimp[\\\/]engine[\\\/]app[\\\/]blimp_browser_main_parts\.cc$",
tfarina0923ac52015-01-07 03:21:22191 r"^chrome[\\\/]browser[\\\/]chromeos[\\\/]boot_times_recorder\.cc$",
sky0e07a142016-03-25 21:27:31192 r"^chrome[\\\/]browser[\\\/]lifetime[\\\/]application_lifetime\.cc$",
alematee4016bb2014-11-12 17:38:51193 r"^chrome[\\\/]browser[\\\/]chromeos[\\\/]"
194 "customization_document_browsertest\.cc$",
philipj3f9d5bde2014-08-28 14:09:09195 r"^components[\\\/]crash[\\\/]app[\\\/]breakpad_mac\.mm$",
jochene9ba6dd2016-02-23 17:20:49196 r"^content[\\\/]shell[\\\/]browser[\\\/]layout_test[\\\/]" +
197 r"test_info_extractor\.cc$",
lukasza7947ccd2016-07-28 21:56:25198 r"^content[\\\/].*browser(|_)test[a-zA-Z_]*\.cc$",
[email protected]de7d61ff2013-08-20 11:30:41199 r"^content[\\\/]shell[\\\/]browser[\\\/]shell_browser_main\.cc$",
200 r"^content[\\\/]shell[\\\/]browser[\\\/]shell_message_filter\.cc$",
lukasza7947ccd2016-07-28 21:56:25201 r"^content[\\\/]test[\\\/]ppapi[\\\/]ppapi_test\.cc$",
jamesra03ae492014-10-03 04:26:48202 r"^mojo[\\\/]edk[\\\/]embedder[\\\/]" +
203 r"simple_platform_shared_buffer_posix\.cc$",
[email protected]398ad132013-04-02 15:11:01204 r"^net[\\\/]disk_cache[\\\/]cache_util\.cc$",
lukasza7947ccd2016-07-28 21:56:25205 r"^net[\\\/]cert[\\\/]test_root_certs\.cc$",
206 r"^net[\\\/]test[\\\/]embedded_test_server[\\\/]" +
207 r"embedded_test_server\.cc$",
208 r"^net[\\\/]test[\\\/]spawned_test_server[\\\/]local_test_server\.cc$",
209 r"^net[\\\/]test[\\\/]test_data_directory\.cc$",
[email protected]1f52a572014-05-12 23:21:54210 r"^net[\\\/]url_request[\\\/]test_url_fetcher_factory\.cc$",
sergeyu2c41f9842016-12-10 01:45:16211 r"^remoting[\\\/]protocol[\\\/]webrtc_transport\.cc$",
lambroslambrouf6fb94ea2016-06-27 21:21:53212 r"^ui[\\\/]base[\\\/]material_design[\\\/]"
213 "material_design_controller\.cc$",
kylechar16666242016-07-04 20:54:45214 r"^ui[\\\/]gl[\\\/]init[\\\/]gl_initializer_mac\.cc$",
215 r"^ui[\\\/]gl[\\\/]init[\\\/]gl_initializer_win\.cc$",
216 r"^ui[\\\/]gl[\\\/]init[\\\/]gl_initializer_x11\.cc$",
217 r"^ui[\\\/]ozone[\\\/]platform[\\\/]drm[\\\/]host[\\\/]"
218 "drm_display_host_manager\.cc$",
[email protected]7345da02012-11-27 14:31:49219 ),
[email protected]23e6cbc2012-06-16 18:51:20220 ),
[email protected]52657f62013-05-20 05:30:31221 (
tomhudsone2c14d552016-05-26 17:07:46222 'setMatrixClip',
223 (
224 'Overriding setMatrixClip() is prohibited; ',
225 'the base function is deprecated. ',
226 ),
227 True,
228 (),
229 ),
230 (
[email protected]52657f62013-05-20 05:30:31231 'SkRefPtr',
232 (
233 'The use of SkRefPtr is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22234 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31235 ),
236 True,
237 (),
238 ),
239 (
240 'SkAutoRef',
241 (
242 'The indirect use of SkRefPtr via SkAutoRef is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22243 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31244 ),
245 True,
246 (),
247 ),
248 (
249 'SkAutoTUnref',
250 (
251 'The use of SkAutoTUnref is dangerous because it implicitly ',
tomhudson7e6e0512016-04-19 19:27:22252 'converts to a raw pointer. Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31253 ),
254 True,
255 (),
256 ),
257 (
258 'SkAutoUnref',
259 (
260 'The indirect use of SkAutoTUnref through SkAutoUnref is dangerous ',
261 'because it implicitly converts to a raw pointer. ',
tomhudson7e6e0512016-04-19 19:27:22262 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31263 ),
264 True,
265 (),
266 ),
[email protected]d89eec82013-12-03 14:10:59267 (
268 r'/HANDLE_EINTR\(.*close',
269 (
270 'HANDLE_EINTR(close) is invalid. If close fails with EINTR, the file',
271 'descriptor will be closed, and it is incorrect to retry the close.',
272 'Either call close directly and ignore its return value, or wrap close',
273 'in IGNORE_EINTR to use its return value. See http://crbug.com/269623'
274 ),
275 True,
276 (),
277 ),
278 (
279 r'/IGNORE_EINTR\((?!.*close)',
280 (
281 'IGNORE_EINTR is only valid when wrapping close. To wrap other system',
282 'calls, use HANDLE_EINTR. See http://crbug.com/269623',
283 ),
284 True,
285 (
286 # Files that #define IGNORE_EINTR.
287 r'^base[\\\/]posix[\\\/]eintr_wrapper\.h$',
288 r'^ppapi[\\\/]tests[\\\/]test_broker\.cc$',
289 ),
290 ),
[email protected]ec5b3f02014-04-04 18:43:43291 (
292 r'/v8::Extension\(',
293 (
294 'Do not introduce new v8::Extensions into the code base, use',
295 'gin::Wrappable instead. See http://crbug.com/334679',
296 ),
297 True,
[email protected]f55c90ee62014-04-12 00:50:03298 (
joaodasilva718f87672014-08-30 09:25:49299 r'extensions[\\\/]renderer[\\\/]safe_builtins\.*',
[email protected]f55c90ee62014-04-12 00:50:03300 ),
[email protected]ec5b3f02014-04-04 18:43:43301 ),
skyostilf9469f72015-04-20 10:38:52302 (
jame2d1a952016-04-02 00:27:10303 '#pragma comment(lib,',
304 (
305 'Specify libraries to link with in build files and not in the source.',
306 ),
307 True,
308 (),
309 ),
[email protected]127f18ec2012-06-16 05:05:59310)
311
wnwenbdc444e2016-05-25 13:44:15312
mlamouria82272622014-09-16 18:45:04313_IPC_ENUM_TRAITS_DEPRECATED = (
314 'You are using IPC_ENUM_TRAITS() in your code. It has been deprecated.\n'
315 'See http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc')
316
[email protected]127f18ec2012-06-16 05:05:59317
[email protected]b00342e7f2013-03-26 16:21:54318_VALID_OS_MACROS = (
319 # Please keep sorted.
320 'OS_ANDROID',
321 'OS_BSD',
322 'OS_CAT', # For testing.
323 'OS_CHROMEOS',
324 'OS_FREEBSD',
325 'OS_IOS',
326 'OS_LINUX',
327 'OS_MACOSX',
328 'OS_NACL',
hidehikof7295f22014-10-28 11:57:21329 'OS_NACL_NONSFI',
330 'OS_NACL_SFI',
krytarowski969759f2016-07-31 23:55:12331 'OS_NETBSD',
[email protected]b00342e7f2013-03-26 16:21:54332 'OS_OPENBSD',
333 'OS_POSIX',
[email protected]eda7afa12014-02-06 12:27:37334 'OS_QNX',
[email protected]b00342e7f2013-03-26 16:21:54335 'OS_SOLARIS',
[email protected]b00342e7f2013-03-26 16:21:54336 'OS_WIN',
337)
338
339
agrievef32bcc72016-04-04 14:57:40340_ANDROID_SPECIFIC_PYDEPS_FILES = [
341 'build/android/test_runner.pydeps',
agrieve732db3a2016-04-26 19:18:19342 'net/tools/testserver/testserver.pydeps',
agrievef32bcc72016-04-04 14:57:40343]
344
wnwenbdc444e2016-05-25 13:44:15345
agrievef32bcc72016-04-04 14:57:40346_GENERIC_PYDEPS_FILES = [
agrievef32bcc72016-04-04 14:57:40347]
348
wnwenbdc444e2016-05-25 13:44:15349
agrievef32bcc72016-04-04 14:57:40350_ALL_PYDEPS_FILES = _ANDROID_SPECIFIC_PYDEPS_FILES + _GENERIC_PYDEPS_FILES
351
352
[email protected]55459852011-08-10 15:17:19353def _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api):
354 """Attempts to prevent use of functions intended only for testing in
355 non-testing code. For now this is just a best-effort implementation
356 that ignores header files and may have some false positives. A
357 better implementation would probably need a proper C++ parser.
358 """
359 # We only scan .cc files and the like, as the declaration of
360 # for-testing functions in header files are hard to distinguish from
361 # calls to such functions without a proper C++ parser.
[email protected]06e6d0ff2012-12-11 01:36:44362 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
[email protected]55459852011-08-10 15:17:19363
jochenc0d4808c2015-07-27 09:25:42364 base_function_pattern = r'[ :]test::[^\s]+|ForTest(s|ing)?|for_test(s|ing)?'
[email protected]55459852011-08-10 15:17:19365 inclusion_pattern = input_api.re.compile(r'(%s)\s*\(' % base_function_pattern)
[email protected]23501822014-05-14 02:06:09366 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_function_pattern)
[email protected]55459852011-08-10 15:17:19367 exclusion_pattern = input_api.re.compile(
368 r'::[A-Za-z0-9_]+(%s)|(%s)[^;]+\{' % (
369 base_function_pattern, base_function_pattern))
370
371 def FilterFile(affected_file):
[email protected]06e6d0ff2012-12-11 01:36:44372 black_list = (_EXCLUDED_PATHS +
373 _TEST_CODE_EXCLUDED_PATHS +
374 input_api.DEFAULT_BLACK_LIST)
[email protected]55459852011-08-10 15:17:19375 return input_api.FilterSourceFile(
376 affected_file,
377 white_list=(file_inclusion_pattern, ),
378 black_list=black_list)
379
380 problems = []
381 for f in input_api.AffectedSourceFiles(FilterFile):
382 local_path = f.LocalPath()
[email protected]825d27182014-01-02 21:24:24383 for line_number, line in f.ChangedContents():
[email protected]2fdd1f362013-01-16 03:56:03384 if (inclusion_pattern.search(line) and
[email protected]de4f7d22013-05-23 14:27:46385 not comment_pattern.search(line) and
[email protected]2fdd1f362013-01-16 03:56:03386 not exclusion_pattern.search(line)):
[email protected]55459852011-08-10 15:17:19387 problems.append(
[email protected]2fdd1f362013-01-16 03:56:03388 '%s:%d\n %s' % (local_path, line_number, line.strip()))
[email protected]55459852011-08-10 15:17:19389
390 if problems:
[email protected]f7051d52013-04-02 18:31:42391 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
[email protected]2fdd1f362013-01-16 03:56:03392 else:
393 return []
[email protected]55459852011-08-10 15:17:19394
395
[email protected]10689ca2011-09-02 02:31:54396def _CheckNoIOStreamInHeaders(input_api, output_api):
397 """Checks to make sure no .h files include <iostream>."""
398 files = []
399 pattern = input_api.re.compile(r'^#include\s*<iostream>',
400 input_api.re.MULTILINE)
401 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
402 if not f.LocalPath().endswith('.h'):
403 continue
404 contents = input_api.ReadFile(f)
405 if pattern.search(contents):
406 files.append(f)
407
408 if len(files):
yolandyandaabc6d2016-04-18 18:29:39409 return [output_api.PresubmitError(
[email protected]6c063c62012-07-11 19:11:06410 'Do not #include <iostream> in header files, since it inserts static '
411 'initialization into every file including the header. Instead, '
[email protected]10689ca2011-09-02 02:31:54412 '#include <ostream>. See http://crbug.com/94794',
413 files) ]
414 return []
415
416
[email protected]72df4e782012-06-21 16:28:18417def _CheckNoUNIT_TESTInSourceFiles(input_api, output_api):
danakj61c1aa22015-10-26 19:55:52418 """Checks to make sure no source files use UNIT_TEST."""
[email protected]72df4e782012-06-21 16:28:18419 problems = []
420 for f in input_api.AffectedFiles():
421 if (not f.LocalPath().endswith(('.cc', '.mm'))):
422 continue
423
424 for line_num, line in f.ChangedContents():
[email protected]549f86a2013-11-19 13:00:04425 if 'UNIT_TEST ' in line or line.endswith('UNIT_TEST'):
[email protected]72df4e782012-06-21 16:28:18426 problems.append(' %s:%d' % (f.LocalPath(), line_num))
427
428 if not problems:
429 return []
430 return [output_api.PresubmitPromptWarning('UNIT_TEST is only for headers.\n' +
431 '\n'.join(problems))]
432
433
danakj61c1aa22015-10-26 19:55:52434def _CheckDCHECK_IS_ONHasBraces(input_api, output_api):
435 """Checks to make sure DCHECK_IS_ON() does not skip the braces."""
436 errors = []
437 pattern = input_api.re.compile(r'DCHECK_IS_ON(?!\(\))',
438 input_api.re.MULTILINE)
439 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
440 if (not f.LocalPath().endswith(('.cc', '.mm', '.h'))):
441 continue
442 for lnum, line in f.ChangedContents():
443 if input_api.re.search(pattern, line):
dchenge07de812016-06-20 19:27:17444 errors.append(output_api.PresubmitError(
445 ('%s:%d: Use of DCHECK_IS_ON() must be written as "#if ' +
446 'DCHECK_IS_ON()", not forgetting the braces.')
447 % (f.LocalPath(), lnum)))
danakj61c1aa22015-10-26 19:55:52448 return errors
449
450
mcasasb7440c282015-02-04 14:52:19451def _FindHistogramNameInLine(histogram_name, line):
452 """Tries to find a histogram name or prefix in a line."""
453 if not "affected-histogram" in line:
454 return histogram_name in line
455 # A histogram_suffixes tag type has an affected-histogram name as a prefix of
456 # the histogram_name.
457 if not '"' in line:
458 return False
459 histogram_prefix = line.split('\"')[1]
460 return histogram_prefix in histogram_name
461
462
463def _CheckUmaHistogramChanges(input_api, output_api):
464 """Check that UMA histogram names in touched lines can still be found in other
465 lines of the patch or in histograms.xml. Note that this check would not catch
466 the reverse: changes in histograms.xml not matched in the code itself."""
467 touched_histograms = []
468 histograms_xml_modifications = []
469 pattern = input_api.re.compile('UMA_HISTOGRAM.*\("(.*)"')
470 for f in input_api.AffectedFiles():
471 # If histograms.xml itself is modified, keep the modified lines for later.
472 if f.LocalPath().endswith(('histograms.xml')):
473 histograms_xml_modifications = f.ChangedContents()
474 continue
475 if not f.LocalPath().endswith(('cc', 'mm', 'cpp')):
476 continue
477 for line_num, line in f.ChangedContents():
478 found = pattern.search(line)
479 if found:
480 touched_histograms.append([found.group(1), f, line_num])
481
482 # Search for the touched histogram names in the local modifications to
483 # histograms.xml, and, if not found, on the base histograms.xml file.
484 unmatched_histograms = []
485 for histogram_info in touched_histograms:
486 histogram_name_found = False
487 for line_num, line in histograms_xml_modifications:
488 histogram_name_found = _FindHistogramNameInLine(histogram_info[0], line)
489 if histogram_name_found:
490 break
491 if not histogram_name_found:
492 unmatched_histograms.append(histogram_info)
493
eromanb90c82e7e32015-04-01 15:13:49494 histograms_xml_path = 'tools/metrics/histograms/histograms.xml'
mcasasb7440c282015-02-04 14:52:19495 problems = []
496 if unmatched_histograms:
eromanb90c82e7e32015-04-01 15:13:49497 with open(histograms_xml_path) as histograms_xml:
mcasasb7440c282015-02-04 14:52:19498 for histogram_name, f, line_num in unmatched_histograms:
mcasas39c1b8b2015-02-25 15:33:45499 histograms_xml.seek(0)
mcasasb7440c282015-02-04 14:52:19500 histogram_name_found = False
501 for line in histograms_xml:
502 histogram_name_found = _FindHistogramNameInLine(histogram_name, line)
503 if histogram_name_found:
504 break
505 if not histogram_name_found:
506 problems.append(' [%s:%d] %s' %
507 (f.LocalPath(), line_num, histogram_name))
508
509 if not problems:
510 return []
511 return [output_api.PresubmitPromptWarning('Some UMA_HISTOGRAM lines have '
512 'been modified and the associated histogram name has no match in either '
eromanb90c82e7e32015-04-01 15:13:49513 '%s or the modifications of it:' % (histograms_xml_path), problems)]
mcasasb7440c282015-02-04 14:52:19514
wnwenbdc444e2016-05-25 13:44:15515
yolandyandaabc6d2016-04-18 18:29:39516def _CheckFlakyTestUsage(input_api, output_api):
517 """Check that FlakyTest annotation is our own instead of the android one"""
518 pattern = input_api.re.compile(r'import android.test.FlakyTest;')
519 files = []
520 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
521 if f.LocalPath().endswith('Test.java'):
522 if pattern.search(input_api.ReadFile(f)):
523 files.append(f)
524 if len(files):
525 return [output_api.PresubmitError(
526 'Use org.chromium.base.test.util.FlakyTest instead of '
527 'android.test.FlakyTest',
528 files)]
529 return []
mcasasb7440c282015-02-04 14:52:19530
wnwenbdc444e2016-05-25 13:44:15531
[email protected]8ea5d4b2011-09-13 21:49:22532def _CheckNoNewWStrings(input_api, output_api):
533 """Checks to make sure we don't introduce use of wstrings."""
[email protected]55463aa62011-10-12 00:48:27534 problems = []
[email protected]8ea5d4b2011-09-13 21:49:22535 for f in input_api.AffectedFiles():
[email protected]b5c24292011-11-28 14:38:20536 if (not f.LocalPath().endswith(('.cc', '.h')) or
scottmge6f04402014-11-05 01:59:57537 f.LocalPath().endswith(('test.cc', '_win.cc', '_win.h')) or
pennymac84fd6692016-07-13 22:35:34538 '/win/' in f.LocalPath() or
539 'chrome_elf' in f.LocalPath() or
540 'install_static' in f.LocalPath()):
[email protected]b5c24292011-11-28 14:38:20541 continue
[email protected]8ea5d4b2011-09-13 21:49:22542
[email protected]a11dbe9b2012-08-07 01:32:58543 allowWString = False
[email protected]b5c24292011-11-28 14:38:20544 for line_num, line in f.ChangedContents():
[email protected]a11dbe9b2012-08-07 01:32:58545 if 'presubmit: allow wstring' in line:
546 allowWString = True
547 elif not allowWString and 'wstring' in line:
[email protected]55463aa62011-10-12 00:48:27548 problems.append(' %s:%d' % (f.LocalPath(), line_num))
[email protected]a11dbe9b2012-08-07 01:32:58549 allowWString = False
550 else:
551 allowWString = False
[email protected]8ea5d4b2011-09-13 21:49:22552
[email protected]55463aa62011-10-12 00:48:27553 if not problems:
554 return []
555 return [output_api.PresubmitPromptWarning('New code should not use wstrings.'
[email protected]a11dbe9b2012-08-07 01:32:58556 ' If you are calling a cross-platform API that accepts a wstring, '
557 'fix the API.\n' +
[email protected]55463aa62011-10-12 00:48:27558 '\n'.join(problems))]
[email protected]8ea5d4b2011-09-13 21:49:22559
560
[email protected]2a8ac9c2011-10-19 17:20:44561def _CheckNoDEPSGIT(input_api, output_api):
562 """Make sure .DEPS.git is never modified manually."""
563 if any(f.LocalPath().endswith('.DEPS.git') for f in
564 input_api.AffectedFiles()):
565 return [output_api.PresubmitError(
566 'Never commit changes to .DEPS.git. This file is maintained by an\n'
567 'automated system based on what\'s in DEPS and your changes will be\n'
568 'overwritten.\n'
[email protected]cb706912014-06-28 20:46:34569 '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:44570 'for more information')]
571 return []
572
573
tandriief664692014-09-23 14:51:47574def _CheckValidHostsInDEPS(input_api, output_api):
575 """Checks that DEPS file deps are from allowed_hosts."""
576 # Run only if DEPS file has been modified to annoy fewer bystanders.
577 if all(f.LocalPath() != 'DEPS' for f in input_api.AffectedFiles()):
578 return []
579 # Outsource work to gclient verify
580 try:
581 input_api.subprocess.check_output(['gclient', 'verify'])
582 return []
583 except input_api.subprocess.CalledProcessError, error:
584 return [output_api.PresubmitError(
585 'DEPS file must have only git dependencies.',
586 long_text=error.output)]
587
588
[email protected]127f18ec2012-06-16 05:05:59589def _CheckNoBannedFunctions(input_api, output_api):
590 """Make sure that banned functions are not used."""
591 warnings = []
592 errors = []
593
wnwenbdc444e2016-05-25 13:44:15594 def IsBlacklisted(affected_file, blacklist):
595 local_path = affected_file.LocalPath()
596 for item in blacklist:
597 if input_api.re.match(item, local_path):
598 return True
599 return False
600
601 def CheckForMatch(affected_file, line_num, line, func_name, message, error):
602 matched = False
603 if func_name[0:1] == '/':
604 regex = func_name[1:]
605 if input_api.re.search(regex, line):
606 matched = True
607 elif func_name in line:
dchenge07de812016-06-20 19:27:17608 matched = True
wnwenbdc444e2016-05-25 13:44:15609 if matched:
dchenge07de812016-06-20 19:27:17610 problems = warnings
wnwenbdc444e2016-05-25 13:44:15611 if error:
dchenge07de812016-06-20 19:27:17612 problems = errors
wnwenbdc444e2016-05-25 13:44:15613 problems.append(' %s:%d:' % (affected_file.LocalPath(), line_num))
614 for message_line in message:
615 problems.append(' %s' % message_line)
616
[email protected]127f18ec2012-06-16 05:05:59617 file_filter = lambda f: f.LocalPath().endswith(('.mm', '.m', '.h'))
618 for f in input_api.AffectedFiles(file_filter=file_filter):
619 for line_num, line in f.ChangedContents():
620 for func_name, message, error in _BANNED_OBJC_FUNCTIONS:
wnwenbdc444e2016-05-25 13:44:15621 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:59622
623 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
624 for f in input_api.AffectedFiles(file_filter=file_filter):
625 for line_num, line in f.ChangedContents():
[email protected]7345da02012-11-27 14:31:49626 for func_name, message, error, excluded_paths in _BANNED_CPP_FUNCTIONS:
[email protected]7345da02012-11-27 14:31:49627 if IsBlacklisted(f, excluded_paths):
628 continue
wnwenbdc444e2016-05-25 13:44:15629 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:59630
631 result = []
632 if (warnings):
633 result.append(output_api.PresubmitPromptWarning(
634 'Banned functions were used.\n' + '\n'.join(warnings)))
635 if (errors):
636 result.append(output_api.PresubmitError(
637 'Banned functions were used.\n' + '\n'.join(errors)))
638 return result
639
640
[email protected]6c063c62012-07-11 19:11:06641def _CheckNoPragmaOnce(input_api, output_api):
642 """Make sure that banned functions are not used."""
643 files = []
644 pattern = input_api.re.compile(r'^#pragma\s+once',
645 input_api.re.MULTILINE)
646 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
647 if not f.LocalPath().endswith('.h'):
648 continue
649 contents = input_api.ReadFile(f)
650 if pattern.search(contents):
651 files.append(f)
652
653 if files:
654 return [output_api.PresubmitError(
655 'Do not use #pragma once in header files.\n'
656 'See http://www.chromium.org/developers/coding-style#TOC-File-headers',
657 files)]
658 return []
659
[email protected]127f18ec2012-06-16 05:05:59660
[email protected]e7479052012-09-19 00:26:12661def _CheckNoTrinaryTrueFalse(input_api, output_api):
662 """Checks to make sure we don't introduce use of foo ? true : false."""
663 problems = []
664 pattern = input_api.re.compile(r'\?\s*(true|false)\s*:\s*(true|false)')
665 for f in input_api.AffectedFiles():
666 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
667 continue
668
669 for line_num, line in f.ChangedContents():
670 if pattern.match(line):
671 problems.append(' %s:%d' % (f.LocalPath(), line_num))
672
673 if not problems:
674 return []
675 return [output_api.PresubmitPromptWarning(
676 'Please consider avoiding the "? true : false" pattern if possible.\n' +
677 '\n'.join(problems))]
678
679
[email protected]55f9f382012-07-31 11:02:18680def _CheckUnwantedDependencies(input_api, output_api):
681 """Runs checkdeps on #include statements added in this
682 change. Breaking - rules is an error, breaking ! rules is a
683 warning.
684 """
mohan.reddyf21db962014-10-16 12:26:47685 import sys
[email protected]55f9f382012-07-31 11:02:18686 # We need to wait until we have an input_api object and use this
687 # roundabout construct to import checkdeps because this file is
688 # eval-ed and thus doesn't have __file__.
689 original_sys_path = sys.path
690 try:
691 sys.path = sys.path + [input_api.os_path.join(
[email protected]5298cc982014-05-29 20:53:47692 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
[email protected]55f9f382012-07-31 11:02:18693 import checkdeps
694 from cpp_checker import CppChecker
695 from rules import Rule
696 finally:
697 # Restore sys.path to what it was before.
698 sys.path = original_sys_path
699
700 added_includes = []
701 for f in input_api.AffectedFiles():
702 if not CppChecker.IsCppFile(f.LocalPath()):
703 continue
704
705 changed_lines = [line for line_num, line in f.ChangedContents()]
706 added_includes.append([f.LocalPath(), changed_lines])
707
[email protected]26385172013-05-09 23:11:35708 deps_checker = checkdeps.DepsChecker(input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:18709
710 error_descriptions = []
711 warning_descriptions = []
712 for path, rule_type, rule_description in deps_checker.CheckAddedCppIncludes(
713 added_includes):
714 description_with_path = '%s\n %s' % (path, rule_description)
715 if rule_type == Rule.DISALLOW:
716 error_descriptions.append(description_with_path)
717 else:
718 warning_descriptions.append(description_with_path)
719
720 results = []
721 if error_descriptions:
722 results.append(output_api.PresubmitError(
723 'You added one or more #includes that violate checkdeps rules.',
724 error_descriptions))
725 if warning_descriptions:
[email protected]f7051d52013-04-02 18:31:42726 results.append(output_api.PresubmitPromptOrNotify(
[email protected]55f9f382012-07-31 11:02:18727 'You added one or more #includes of files that are temporarily\n'
728 'allowed but being removed. Can you avoid introducing the\n'
729 '#include? See relevant DEPS file(s) for details and contacts.',
730 warning_descriptions))
731 return results
732
733
[email protected]fbcafe5a2012-08-08 15:31:22734def _CheckFilePermissions(input_api, output_api):
735 """Check that all files have their permissions properly set."""
[email protected]791507202014-02-03 23:19:15736 if input_api.platform == 'win32':
737 return []
raphael.kubo.da.costac1d13e60b2016-04-01 11:49:29738 checkperms_tool = input_api.os_path.join(
739 input_api.PresubmitLocalPath(),
740 'tools', 'checkperms', 'checkperms.py')
741 args = [input_api.python_executable, checkperms_tool,
mohan.reddyf21db962014-10-16 12:26:47742 '--root', input_api.change.RepositoryRoot()]
[email protected]fbcafe5a2012-08-08 15:31:22743 for f in input_api.AffectedFiles():
744 args += ['--file', f.LocalPath()]
phajdan.jr5ea54792015-10-14 10:51:11745 try:
746 input_api.subprocess.check_output(args)
747 return []
748 except input_api.subprocess.CalledProcessError as error:
749 return [output_api.PresubmitError(
750 'checkperms.py failed:',
751 long_text=error.output)]
[email protected]fbcafe5a2012-08-08 15:31:22752
753
robertocn832f5992017-01-04 19:01:30754def _CheckTeamTags(input_api, output_api):
755 """Checks that OWNERS files have consistent TEAM and COMPONENT tags."""
756 checkteamtags_tool = input_api.os_path.join(
757 input_api.PresubmitLocalPath(),
758 'tools', 'checkteamtags', 'checkteamtags.py')
759 args = [input_api.python_executable, checkteamtags_tool,
760 '--root', input_api.change.RepositoryRoot()]
robertocn5eb82312017-01-09 20:27:22761 files = [f.LocalPath() for f in input_api.AffectedFiles(include_deletes=False)
robertocn832f5992017-01-04 19:01:30762 if input_api.os_path.basename(f.AbsoluteLocalPath()).upper() ==
763 'OWNERS']
764 try:
765 if files:
766 input_api.subprocess.check_output(args + files)
767 return []
768 except input_api.subprocess.CalledProcessError as error:
769 return [output_api.PresubmitError(
770 'checkteamtags.py failed:',
771 long_text=error.output)]
772
773
[email protected]c8278b32012-10-30 20:35:49774def _CheckNoAuraWindowPropertyHInHeaders(input_api, output_api):
775 """Makes sure we don't include ui/aura/window_property.h
776 in header files.
777 """
778 pattern = input_api.re.compile(r'^#include\s*"ui/aura/window_property.h"')
779 errors = []
780 for f in input_api.AffectedFiles():
781 if not f.LocalPath().endswith('.h'):
782 continue
783 for line_num, line in f.ChangedContents():
784 if pattern.match(line):
785 errors.append(' %s:%d' % (f.LocalPath(), line_num))
786
787 results = []
788 if errors:
789 results.append(output_api.PresubmitError(
790 'Header files should not include ui/aura/window_property.h', errors))
791 return results
792
793
[email protected]cf9b78f2012-11-14 11:40:28794def _CheckIncludeOrderForScope(scope, input_api, file_path, changed_linenums):
795 """Checks that the lines in scope occur in the right order.
796
797 1. C system files in alphabetical order
798 2. C++ system files in alphabetical order
799 3. Project's .h files
800 """
801
802 c_system_include_pattern = input_api.re.compile(r'\s*#include <.*\.h>')
803 cpp_system_include_pattern = input_api.re.compile(r'\s*#include <.*>')
804 custom_include_pattern = input_api.re.compile(r'\s*#include ".*')
805
806 C_SYSTEM_INCLUDES, CPP_SYSTEM_INCLUDES, CUSTOM_INCLUDES = range(3)
807
808 state = C_SYSTEM_INCLUDES
809
810 previous_line = ''
[email protected]728b9bb2012-11-14 20:38:57811 previous_line_num = 0
[email protected]cf9b78f2012-11-14 11:40:28812 problem_linenums = []
brucedawson70fadb02015-06-30 17:47:55813 out_of_order = " - line belongs before previous line"
[email protected]cf9b78f2012-11-14 11:40:28814 for line_num, line in scope:
815 if c_system_include_pattern.match(line):
816 if state != C_SYSTEM_INCLUDES:
brucedawson70fadb02015-06-30 17:47:55817 problem_linenums.append((line_num, previous_line_num,
818 " - C system include file in wrong block"))
[email protected]cf9b78f2012-11-14 11:40:28819 elif previous_line and previous_line > line:
brucedawson70fadb02015-06-30 17:47:55820 problem_linenums.append((line_num, previous_line_num,
821 out_of_order))
[email protected]cf9b78f2012-11-14 11:40:28822 elif cpp_system_include_pattern.match(line):
823 if state == C_SYSTEM_INCLUDES:
824 state = CPP_SYSTEM_INCLUDES
825 elif state == CUSTOM_INCLUDES:
brucedawson70fadb02015-06-30 17:47:55826 problem_linenums.append((line_num, previous_line_num,
827 " - c++ system include file in wrong block"))
[email protected]cf9b78f2012-11-14 11:40:28828 elif previous_line and previous_line > line:
brucedawson70fadb02015-06-30 17:47:55829 problem_linenums.append((line_num, previous_line_num, out_of_order))
[email protected]cf9b78f2012-11-14 11:40:28830 elif custom_include_pattern.match(line):
831 if state != CUSTOM_INCLUDES:
832 state = CUSTOM_INCLUDES
833 elif previous_line and previous_line > line:
brucedawson70fadb02015-06-30 17:47:55834 problem_linenums.append((line_num, previous_line_num, out_of_order))
[email protected]cf9b78f2012-11-14 11:40:28835 else:
brucedawson70fadb02015-06-30 17:47:55836 problem_linenums.append((line_num, previous_line_num,
837 "Unknown include type"))
[email protected]cf9b78f2012-11-14 11:40:28838 previous_line = line
[email protected]728b9bb2012-11-14 20:38:57839 previous_line_num = line_num
[email protected]cf9b78f2012-11-14 11:40:28840
841 warnings = []
brucedawson70fadb02015-06-30 17:47:55842 for (line_num, previous_line_num, failure_type) in problem_linenums:
[email protected]728b9bb2012-11-14 20:38:57843 if line_num in changed_linenums or previous_line_num in changed_linenums:
brucedawson70fadb02015-06-30 17:47:55844 warnings.append(' %s:%d:%s' % (file_path, line_num, failure_type))
[email protected]cf9b78f2012-11-14 11:40:28845 return warnings
846
847
[email protected]ac294a12012-12-06 16:38:43848def _CheckIncludeOrderInFile(input_api, f, changed_linenums):
[email protected]cf9b78f2012-11-14 11:40:28849 """Checks the #include order for the given file f."""
850
[email protected]2299dcf2012-11-15 19:56:24851 system_include_pattern = input_api.re.compile(r'\s*#include \<.*')
[email protected]23093b62013-09-20 12:16:30852 # Exclude the following includes from the check:
853 # 1) #include <.../...>, e.g., <sys/...> includes often need to appear in a
854 # specific order.
855 # 2) <atlbase.h>, "build/build_config.h"
856 excluded_include_pattern = input_api.re.compile(
857 r'\s*#include (\<.*/.*|\<atlbase\.h\>|"build/build_config.h")')
[email protected]2299dcf2012-11-15 19:56:24858 custom_include_pattern = input_api.re.compile(r'\s*#include "(?P<FILE>.*)"')
[email protected]3e83618c2013-10-09 22:32:33859 # Match the final or penultimate token if it is xxxtest so we can ignore it
860 # when considering the special first include.
861 test_file_tag_pattern = input_api.re.compile(
862 r'_[a-z]+test(?=(_[a-zA-Z0-9]+)?\.)')
[email protected]0e5c1852012-12-18 20:17:11863 if_pattern = input_api.re.compile(
864 r'\s*#\s*(if|elif|else|endif|define|undef).*')
865 # Some files need specialized order of includes; exclude such files from this
866 # check.
867 uncheckable_includes_pattern = input_api.re.compile(
868 r'\s*#include '
869 '("ipc/.*macros\.h"|<windows\.h>|".*gl.*autogen.h")\s*')
[email protected]cf9b78f2012-11-14 11:40:28870
871 contents = f.NewContents()
872 warnings = []
873 line_num = 0
874
[email protected]ac294a12012-12-06 16:38:43875 # Handle the special first include. If the first include file is
876 # some/path/file.h, the corresponding including file can be some/path/file.cc,
877 # some/other/path/file.cc, some/path/file_platform.cc, some/path/file-suffix.h
878 # etc. It's also possible that no special first include exists.
[email protected]3e83618c2013-10-09 22:32:33879 # If the included file is some/path/file_platform.h the including file could
880 # also be some/path/file_xxxtest_platform.h.
881 including_file_base_name = test_file_tag_pattern.sub(
882 '', input_api.os_path.basename(f.LocalPath()))
883
[email protected]ac294a12012-12-06 16:38:43884 for line in contents:
885 line_num += 1
886 if system_include_pattern.match(line):
887 # No special first include -> process the line again along with normal
888 # includes.
889 line_num -= 1
890 break
891 match = custom_include_pattern.match(line)
892 if match:
893 match_dict = match.groupdict()
[email protected]3e83618c2013-10-09 22:32:33894 header_basename = test_file_tag_pattern.sub(
895 '', input_api.os_path.basename(match_dict['FILE'])).replace('.h', '')
896
897 if header_basename not in including_file_base_name:
[email protected]2299dcf2012-11-15 19:56:24898 # No special first include -> process the line again along with normal
899 # includes.
900 line_num -= 1
[email protected]ac294a12012-12-06 16:38:43901 break
[email protected]cf9b78f2012-11-14 11:40:28902
903 # Split into scopes: Each region between #if and #endif is its own scope.
904 scopes = []
905 current_scope = []
906 for line in contents[line_num:]:
907 line_num += 1
[email protected]0e5c1852012-12-18 20:17:11908 if uncheckable_includes_pattern.match(line):
[email protected]4436c9e2014-01-07 23:19:54909 continue
[email protected]2309b0fa02012-11-16 12:18:27910 if if_pattern.match(line):
[email protected]cf9b78f2012-11-14 11:40:28911 scopes.append(current_scope)
912 current_scope = []
[email protected]962f117e2012-11-22 18:11:56913 elif ((system_include_pattern.match(line) or
914 custom_include_pattern.match(line)) and
915 not excluded_include_pattern.match(line)):
[email protected]cf9b78f2012-11-14 11:40:28916 current_scope.append((line_num, line))
917 scopes.append(current_scope)
918
919 for scope in scopes:
920 warnings.extend(_CheckIncludeOrderForScope(scope, input_api, f.LocalPath(),
921 changed_linenums))
922 return warnings
923
924
925def _CheckIncludeOrder(input_api, output_api):
926 """Checks that the #include order is correct.
927
928 1. The corresponding header for source files.
929 2. C system files in alphabetical order
930 3. C++ system files in alphabetical order
931 4. Project's .h files in alphabetical order
932
[email protected]ac294a12012-12-06 16:38:43933 Each region separated by #if, #elif, #else, #endif, #define and #undef follows
934 these rules separately.
[email protected]cf9b78f2012-11-14 11:40:28935 """
[email protected]e120b012014-08-15 19:08:35936 def FileFilterIncludeOrder(affected_file):
937 black_list = (_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
938 return input_api.FilterSourceFile(affected_file, black_list=black_list)
[email protected]cf9b78f2012-11-14 11:40:28939
940 warnings = []
[email protected]e120b012014-08-15 19:08:35941 for f in input_api.AffectedFiles(file_filter=FileFilterIncludeOrder):
tapted574f09c2015-05-19 13:08:08942 if f.LocalPath().endswith(('.cc', '.h', '.mm')):
[email protected]ac294a12012-12-06 16:38:43943 changed_linenums = set(line_num for line_num, _ in f.ChangedContents())
944 warnings.extend(_CheckIncludeOrderInFile(input_api, f, changed_linenums))
[email protected]cf9b78f2012-11-14 11:40:28945
946 results = []
947 if warnings:
[email protected]f7051d52013-04-02 18:31:42948 results.append(output_api.PresubmitPromptOrNotify(_INCLUDE_ORDER_WARNING,
[email protected]120cf540d2012-12-10 17:55:53949 warnings))
[email protected]cf9b78f2012-11-14 11:40:28950 return results
951
952
[email protected]70ca77752012-11-20 03:45:03953def _CheckForVersionControlConflictsInFile(input_api, f):
954 pattern = input_api.re.compile('^(?:<<<<<<<|>>>>>>>) |^=======$')
955 errors = []
956 for line_num, line in f.ChangedContents():
dbeam95c35a2f2015-06-02 01:40:23957 if f.LocalPath().endswith('.md'):
958 # First-level headers in markdown look a lot like version control
959 # conflict markers. http://daringfireball.net/projects/markdown/basics
960 continue
[email protected]70ca77752012-11-20 03:45:03961 if pattern.match(line):
962 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
963 return errors
964
965
966def _CheckForVersionControlConflicts(input_api, output_api):
967 """Usually this is not intentional and will cause a compile failure."""
968 errors = []
969 for f in input_api.AffectedFiles():
970 errors.extend(_CheckForVersionControlConflictsInFile(input_api, f))
971
972 results = []
973 if errors:
974 results.append(output_api.PresubmitError(
975 'Version control conflict markers found, please resolve.', errors))
976 return results
977
estadee17314a02017-01-12 16:22:16978def _CheckGoogleSupportAnswerUrl(input_api, output_api):
979 pattern = input_api.re.compile('support\.google\.com\/chrome.*/answer')
980 errors = []
981 for f in input_api.AffectedFiles():
982 for line_num, line in f.ChangedContents():
983 if pattern.search(line):
984 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
985
986 results = []
987 if errors:
988 results.append(output_api.PresubmitPromptWarning(
989 'Found Google support URL addressed by answer number. Please replace with '
990 'a p= identifier instead. See crbug.com/679462\n', errors))
991 return results
992
[email protected]70ca77752012-11-20 03:45:03993
[email protected]06e6d0ff2012-12-11 01:36:44994def _CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api):
995 def FilterFile(affected_file):
996 """Filter function for use with input_api.AffectedSourceFiles,
997 below. This filters out everything except non-test files from
998 top-level directories that generally speaking should not hard-code
999 service URLs (e.g. src/android_webview/, src/content/ and others).
1000 """
1001 return input_api.FilterSourceFile(
1002 affected_file,
[email protected]78bb39d62012-12-11 15:11:561003 white_list=(r'^(android_webview|base|content|net)[\\\/].*', ),
[email protected]06e6d0ff2012-12-11 01:36:441004 black_list=(_EXCLUDED_PATHS +
1005 _TEST_CODE_EXCLUDED_PATHS +
1006 input_api.DEFAULT_BLACK_LIST))
1007
reillyi38965732015-11-16 18:27:331008 base_pattern = ('"[^"]*(google|googleapis|googlezip|googledrive|appspot)'
1009 '\.(com|net)[^"]*"')
[email protected]de4f7d22013-05-23 14:27:461010 comment_pattern = input_api.re.compile('//.*%s' % base_pattern)
1011 pattern = input_api.re.compile(base_pattern)
[email protected]06e6d0ff2012-12-11 01:36:441012 problems = [] # items are (filename, line_number, line)
1013 for f in input_api.AffectedSourceFiles(FilterFile):
1014 for line_num, line in f.ChangedContents():
[email protected]de4f7d22013-05-23 14:27:461015 if not comment_pattern.search(line) and pattern.search(line):
[email protected]06e6d0ff2012-12-11 01:36:441016 problems.append((f.LocalPath(), line_num, line))
1017
1018 if problems:
[email protected]f7051d52013-04-02 18:31:421019 return [output_api.PresubmitPromptOrNotify(
[email protected]06e6d0ff2012-12-11 01:36:441020 'Most layers below src/chrome/ should not hardcode service URLs.\n'
[email protected]b0149772014-03-27 16:47:581021 'Are you sure this is correct?',
[email protected]06e6d0ff2012-12-11 01:36:441022 [' %s:%d: %s' % (
1023 problem[0], problem[1], problem[2]) for problem in problems])]
[email protected]2fdd1f362013-01-16 03:56:031024 else:
1025 return []
[email protected]06e6d0ff2012-12-11 01:36:441026
1027
[email protected]d2530012013-01-25 16:39:271028def _CheckNoAbbreviationInPngFileName(input_api, output_api):
1029 """Makes sure there are no abbreviations in the name of PNG files.
binji0dcdf342014-12-12 18:32:311030 The native_client_sdk directory is excluded because it has auto-generated PNG
1031 files for documentation.
[email protected]d2530012013-01-25 16:39:271032 """
[email protected]d2530012013-01-25 16:39:271033 errors = []
binji0dcdf342014-12-12 18:32:311034 white_list = (r'.*_[a-z]_.*\.png$|.*_[a-z]\.png$',)
1035 black_list = (r'^native_client_sdk[\\\/]',)
1036 file_filter = lambda f: input_api.FilterSourceFile(
1037 f, white_list=white_list, black_list=black_list)
1038 for f in input_api.AffectedFiles(include_deletes=False,
1039 file_filter=file_filter):
1040 errors.append(' %s' % f.LocalPath())
[email protected]d2530012013-01-25 16:39:271041
1042 results = []
1043 if errors:
1044 results.append(output_api.PresubmitError(
1045 'The name of PNG files should not have abbreviations. \n'
1046 'Use _hover.png, _center.png, instead of _h.png, _c.png.\n'
1047 'Contact [email protected] if you have questions.', errors))
1048 return results
1049
1050
[email protected]14a6131c2014-01-08 01:15:411051def _FilesToCheckForIncomingDeps(re, changed_lines):
[email protected]f32e2d1e2013-07-26 21:39:081052 """Helper method for _CheckAddedDepsHaveTargetApprovals. Returns
[email protected]14a6131c2014-01-08 01:15:411053 a set of DEPS entries that we should look up.
1054
1055 For a directory (rather than a specific filename) we fake a path to
1056 a specific filename by adding /DEPS. This is chosen as a file that
1057 will seldom or never be subject to per-file include_rules.
1058 """
[email protected]2b438d62013-11-14 17:54:141059 # We ignore deps entries on auto-generated directories.
1060 AUTO_GENERATED_DIRS = ['grit', 'jni']
[email protected]f32e2d1e2013-07-26 21:39:081061
1062 # This pattern grabs the path without basename in the first
1063 # parentheses, and the basename (if present) in the second. It
1064 # relies on the simple heuristic that if there is a basename it will
1065 # be a header file ending in ".h".
1066 pattern = re.compile(
1067 r"""['"]\+([^'"]+?)(/[a-zA-Z0-9_]+\.h)?['"].*""")
[email protected]2b438d62013-11-14 17:54:141068 results = set()
[email protected]f32e2d1e2013-07-26 21:39:081069 for changed_line in changed_lines:
1070 m = pattern.match(changed_line)
1071 if m:
1072 path = m.group(1)
[email protected]2b438d62013-11-14 17:54:141073 if path.split('/')[0] not in AUTO_GENERATED_DIRS:
[email protected]14a6131c2014-01-08 01:15:411074 if m.group(2):
1075 results.add('%s%s' % (path, m.group(2)))
1076 else:
1077 results.add('%s/DEPS' % path)
[email protected]f32e2d1e2013-07-26 21:39:081078 return results
1079
1080
[email protected]e871964c2013-05-13 14:14:551081def _CheckAddedDepsHaveTargetApprovals(input_api, output_api):
1082 """When a dependency prefixed with + is added to a DEPS file, we
1083 want to make sure that the change is reviewed by an OWNER of the
1084 target file or directory, to avoid layering violations from being
1085 introduced. This check verifies that this happens.
1086 """
1087 changed_lines = set()
jochen53efcdd2016-01-29 05:09:241088
1089 file_filter = lambda f: not input_api.re.match(
1090 r"^third_party[\\\/]WebKit[\\\/].*", f.LocalPath())
1091 for f in input_api.AffectedFiles(include_deletes=False,
1092 file_filter=file_filter):
[email protected]e871964c2013-05-13 14:14:551093 filename = input_api.os_path.basename(f.LocalPath())
1094 if filename == 'DEPS':
1095 changed_lines |= set(line.strip()
1096 for line_num, line
1097 in f.ChangedContents())
1098 if not changed_lines:
1099 return []
1100
[email protected]14a6131c2014-01-08 01:15:411101 virtual_depended_on_files = _FilesToCheckForIncomingDeps(input_api.re,
1102 changed_lines)
[email protected]e871964c2013-05-13 14:14:551103 if not virtual_depended_on_files:
1104 return []
1105
1106 if input_api.is_committing:
1107 if input_api.tbr:
1108 return [output_api.PresubmitNotifyResult(
1109 '--tbr was specified, skipping OWNERS check for DEPS additions')]
Paweł Hajdan, Jrbe6739ea2016-04-28 15:07:271110 if input_api.dry_run:
1111 return [output_api.PresubmitNotifyResult(
1112 'This is a dry run, skipping OWNERS check for DEPS additions')]
[email protected]e871964c2013-05-13 14:14:551113 if not input_api.change.issue:
1114 return [output_api.PresubmitError(
1115 "DEPS approval by OWNERS check failed: this change has "
1116 "no Rietveld issue number, so we can't check it for approvals.")]
1117 output = output_api.PresubmitError
1118 else:
1119 output = output_api.PresubmitNotifyResult
1120
1121 owners_db = input_api.owners_db
tandriied3b7e12016-05-12 14:38:501122 owner_email, reviewers = (
1123 input_api.canned_checks.GetCodereviewOwnerAndReviewers(
1124 input_api,
1125 owners_db.email_regexp,
1126 approval_needed=input_api.is_committing))
[email protected]e871964c2013-05-13 14:14:551127
1128 owner_email = owner_email or input_api.change.author_email
1129
[email protected]de4f7d22013-05-23 14:27:461130 reviewers_plus_owner = set(reviewers)
[email protected]e71c6082013-05-22 02:28:511131 if owner_email:
[email protected]de4f7d22013-05-23 14:27:461132 reviewers_plus_owner.add(owner_email)
[email protected]e871964c2013-05-13 14:14:551133 missing_files = owners_db.files_not_covered_by(virtual_depended_on_files,
1134 reviewers_plus_owner)
[email protected]14a6131c2014-01-08 01:15:411135
1136 # We strip the /DEPS part that was added by
1137 # _FilesToCheckForIncomingDeps to fake a path to a file in a
1138 # directory.
1139 def StripDeps(path):
1140 start_deps = path.rfind('/DEPS')
1141 if start_deps != -1:
1142 return path[:start_deps]
1143 else:
1144 return path
1145 unapproved_dependencies = ["'+%s'," % StripDeps(path)
[email protected]e871964c2013-05-13 14:14:551146 for path in missing_files]
1147
1148 if unapproved_dependencies:
1149 output_list = [
Paweł Hajdan, Jrec17f882016-07-04 14:16:151150 output('You need LGTM from owners of depends-on paths in DEPS that were '
1151 'modified in this CL:\n %s' %
1152 '\n '.join(sorted(unapproved_dependencies)))]
1153 suggested_owners = owners_db.reviewers_for(missing_files, owner_email)
1154 output_list.append(output(
1155 'Suggested missing target path OWNERS:\n %s' %
1156 '\n '.join(suggested_owners or [])))
[email protected]e871964c2013-05-13 14:14:551157 return output_list
1158
1159 return []
1160
1161
[email protected]85218562013-11-22 07:41:401162def _CheckSpamLogging(input_api, output_api):
1163 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
1164 black_list = (_EXCLUDED_PATHS +
1165 _TEST_CODE_EXCLUDED_PATHS +
1166 input_api.DEFAULT_BLACK_LIST +
[email protected]6f742dd02013-11-26 23:19:501167 (r"^base[\\\/]logging\.h$",
[email protected]80f360a2014-01-23 01:36:191168 r"^base[\\\/]logging\.cc$",
[email protected]8dc338c2013-12-09 16:28:481169 r"^chrome[\\\/]app[\\\/]chrome_main_delegate\.cc$",
[email protected]6e268db2013-12-04 01:41:461170 r"^chrome[\\\/]browser[\\\/]chrome_browser_main\.cc$",
[email protected]4de75262013-12-18 23:16:121171 r"^chrome[\\\/]browser[\\\/]ui[\\\/]startup[\\\/]"
1172 r"startup_browser_creator\.cc$",
[email protected]fe0e6e12013-12-04 05:52:581173 r"^chrome[\\\/]installer[\\\/]setup[\\\/].*",
[email protected]8cf6f842014-08-08 21:33:161174 r"chrome[\\\/]browser[\\\/]diagnostics[\\\/]" +
[email protected]f5b9a3f342014-08-08 22:06:031175 r"diagnostics_writer\.cc$",
[email protected]9f13b602014-08-07 02:59:151176 r"^chrome_elf[\\\/]dll_hash[\\\/]dll_hash_main\.cc$",
1177 r"^chromecast[\\\/]",
1178 r"^cloud_print[\\\/]",
jochen34415e52015-07-10 08:34:311179 r"^components[\\\/]html_viewer[\\\/]"
1180 r"web_test_delegate_impl\.cc$",
peter80739bb2015-10-20 11:17:461181 # TODO(peter): Remove this exception. https://crbug.com/534537
1182 r"^content[\\\/]browser[\\\/]notifications[\\\/]"
1183 r"notification_event_dispatcher_impl\.cc$",
[email protected]9056e732014-01-08 06:25:251184 r"^content[\\\/]common[\\\/]gpu[\\\/]client[\\\/]"
1185 r"gl_helper_benchmark\.cc$",
altimin979ea2e12016-05-18 16:16:241186 r"^courgette[\\\/]courgette_minimal_tool\.cc$",
thestigc9e38a22014-09-13 01:02:111187 r"^courgette[\\\/]courgette_tool\.cc$",
[email protected]9f13b602014-08-07 02:59:151188 r"^extensions[\\\/]renderer[\\\/]logging_native_handler\.cc$",
prashant.nb0252f62014-11-08 05:02:111189 r"^ipc[\\\/]ipc_logging\.cc$",
[email protected]9c36d922014-03-24 16:47:521190 r"^native_client_sdk[\\\/]",
[email protected]cdbdced2013-11-27 21:35:501191 r"^remoting[\\\/]base[\\\/]logging\.h$",
[email protected]67c96ab2013-12-17 02:05:361192 r"^remoting[\\\/]host[\\\/].*",
[email protected]8232f8fd2013-12-14 00:52:311193 r"^sandbox[\\\/]linux[\\\/].*",
[email protected]0b7a21e2014-02-11 18:38:131194 r"^tools[\\\/]",
thestig22dfc4012014-09-05 08:29:441195 r"^ui[\\\/]aura[\\\/]bench[\\\/]bench_main\.cc$",
halliwellf7fc61c62016-01-28 17:18:451196 r"^ui[\\\/]ozone[\\\/]platform[\\\/]cast[\\\/]",
vchigrin14251492015-01-12 08:09:021197 r"^storage[\\\/]browser[\\\/]fileapi[\\\/]" +
skyostil87681be82016-12-19 12:46:351198 r"dump_file_system.cc$",
1199 r"^headless[\\\/]app[\\\/]headless_shell\.cc$"))
[email protected]85218562013-11-22 07:41:401200 source_file_filter = lambda x: input_api.FilterSourceFile(
1201 x, white_list=(file_inclusion_pattern,), black_list=black_list)
1202
1203 log_info = []
1204 printf = []
1205
1206 for f in input_api.AffectedSourceFiles(source_file_filter):
1207 contents = input_api.ReadFile(f, 'rb')
mohan.reddyf21db962014-10-16 12:26:471208 if input_api.re.search(r"\bD?LOG\s*\(\s*INFO\s*\)", contents):
[email protected]85218562013-11-22 07:41:401209 log_info.append(f.LocalPath())
mohan.reddyf21db962014-10-16 12:26:471210 elif input_api.re.search(r"\bD?LOG_IF\s*\(\s*INFO\s*,", contents):
[email protected]85210652013-11-28 05:50:131211 log_info.append(f.LocalPath())
[email protected]18b466b2013-12-02 22:01:371212
mohan.reddyf21db962014-10-16 12:26:471213 if input_api.re.search(r"\bprintf\(", contents):
[email protected]18b466b2013-12-02 22:01:371214 printf.append(f.LocalPath())
mohan.reddyf21db962014-10-16 12:26:471215 elif input_api.re.search(r"\bfprintf\((stdout|stderr)", contents):
[email protected]85218562013-11-22 07:41:401216 printf.append(f.LocalPath())
1217
1218 if log_info:
1219 return [output_api.PresubmitError(
1220 'These files spam the console log with LOG(INFO):',
1221 items=log_info)]
1222 if printf:
1223 return [output_api.PresubmitError(
1224 'These files spam the console log with printf/fprintf:',
1225 items=printf)]
1226 return []
1227
1228
[email protected]49aa76a2013-12-04 06:59:161229def _CheckForAnonymousVariables(input_api, output_api):
1230 """These types are all expected to hold locks while in scope and
1231 so should never be anonymous (which causes them to be immediately
1232 destroyed)."""
1233 they_who_must_be_named = [
1234 'base::AutoLock',
1235 'base::AutoReset',
1236 'base::AutoUnlock',
1237 'SkAutoAlphaRestore',
1238 'SkAutoBitmapShaderInstall',
1239 'SkAutoBlitterChoose',
1240 'SkAutoBounderCommit',
1241 'SkAutoCallProc',
1242 'SkAutoCanvasRestore',
1243 'SkAutoCommentBlock',
1244 'SkAutoDescriptor',
1245 'SkAutoDisableDirectionCheck',
1246 'SkAutoDisableOvalCheck',
1247 'SkAutoFree',
1248 'SkAutoGlyphCache',
1249 'SkAutoHDC',
1250 'SkAutoLockColors',
1251 'SkAutoLockPixels',
1252 'SkAutoMalloc',
1253 'SkAutoMaskFreeImage',
1254 'SkAutoMutexAcquire',
1255 'SkAutoPathBoundsUpdate',
1256 'SkAutoPDFRelease',
1257 'SkAutoRasterClipValidate',
1258 'SkAutoRef',
1259 'SkAutoTime',
1260 'SkAutoTrace',
1261 'SkAutoUnref',
1262 ]
1263 anonymous = r'(%s)\s*[({]' % '|'.join(they_who_must_be_named)
1264 # bad: base::AutoLock(lock.get());
1265 # not bad: base::AutoLock lock(lock.get());
1266 bad_pattern = input_api.re.compile(anonymous)
1267 # good: new base::AutoLock(lock.get())
1268 good_pattern = input_api.re.compile(r'\bnew\s*' + anonymous)
1269 errors = []
1270
1271 for f in input_api.AffectedFiles():
1272 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
1273 continue
1274 for linenum, line in f.ChangedContents():
1275 if bad_pattern.search(line) and not good_pattern.search(line):
1276 errors.append('%s:%d' % (f.LocalPath(), linenum))
1277
1278 if errors:
1279 return [output_api.PresubmitError(
1280 'These lines create anonymous variables that need to be named:',
1281 items=errors)]
1282 return []
1283
1284
[email protected]5fe0f8742013-11-29 01:04:591285def _CheckCygwinShell(input_api, output_api):
1286 source_file_filter = lambda x: input_api.FilterSourceFile(
1287 x, white_list=(r'.+\.(gyp|gypi)$',))
1288 cygwin_shell = []
1289
1290 for f in input_api.AffectedSourceFiles(source_file_filter):
1291 for linenum, line in f.ChangedContents():
1292 if 'msvs_cygwin_shell' in line:
1293 cygwin_shell.append(f.LocalPath())
1294 break
1295
1296 if cygwin_shell:
1297 return [output_api.PresubmitError(
1298 'These files should not use msvs_cygwin_shell (the default is 0):',
1299 items=cygwin_shell)]
1300 return []
1301
[email protected]85218562013-11-22 07:41:401302
[email protected]999261d2014-03-03 20:08:081303def _CheckUserActionUpdate(input_api, output_api):
1304 """Checks if any new user action has been added."""
[email protected]2f92dec2014-03-07 19:21:521305 if any('actions.xml' == input_api.os_path.basename(f) for f in
[email protected]999261d2014-03-03 20:08:081306 input_api.LocalPaths()):
[email protected]2f92dec2014-03-07 19:21:521307 # If actions.xml is already included in the changelist, the PRESUBMIT
1308 # for actions.xml will do a more complete presubmit check.
[email protected]999261d2014-03-03 20:08:081309 return []
1310
[email protected]999261d2014-03-03 20:08:081311 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm'))
1312 action_re = r'[^a-zA-Z]UserMetricsAction\("([^"]*)'
[email protected]2f92dec2014-03-07 19:21:521313 current_actions = None
[email protected]999261d2014-03-03 20:08:081314 for f in input_api.AffectedFiles(file_filter=file_filter):
1315 for line_num, line in f.ChangedContents():
1316 match = input_api.re.search(action_re, line)
1317 if match:
[email protected]2f92dec2014-03-07 19:21:521318 # Loads contents in tools/metrics/actions/actions.xml to memory. It's
1319 # loaded only once.
1320 if not current_actions:
1321 with open('tools/metrics/actions/actions.xml') as actions_f:
1322 current_actions = actions_f.read()
1323 # Search for the matched user action name in |current_actions|.
[email protected]999261d2014-03-03 20:08:081324 for action_name in match.groups():
[email protected]2f92dec2014-03-07 19:21:521325 action = 'name="{0}"'.format(action_name)
1326 if action not in current_actions:
[email protected]999261d2014-03-03 20:08:081327 return [output_api.PresubmitPromptWarning(
1328 'File %s line %d: %s is missing in '
[email protected]2f92dec2014-03-07 19:21:521329 'tools/metrics/actions/actions.xml. Please run '
1330 'tools/metrics/actions/extract_actions.py to update.'
[email protected]999261d2014-03-03 20:08:081331 % (f.LocalPath(), line_num, action_name))]
1332 return []
1333
1334
[email protected]99171a92014-06-03 08:44:471335def _GetJSONParseError(input_api, filename, eat_comments=True):
1336 try:
1337 contents = input_api.ReadFile(filename)
1338 if eat_comments:
plundblad1f5a4509f2015-07-23 11:31:131339 import sys
1340 original_sys_path = sys.path
1341 try:
1342 sys.path = sys.path + [input_api.os_path.join(
1343 input_api.PresubmitLocalPath(),
1344 'tools', 'json_comment_eater')]
1345 import json_comment_eater
1346 finally:
1347 sys.path = original_sys_path
1348 contents = json_comment_eater.Nom(contents)
[email protected]99171a92014-06-03 08:44:471349
1350 input_api.json.loads(contents)
1351 except ValueError as e:
1352 return e
1353 return None
1354
1355
1356def _GetIDLParseError(input_api, filename):
1357 try:
1358 contents = input_api.ReadFile(filename)
1359 idl_schema = input_api.os_path.join(
1360 input_api.PresubmitLocalPath(),
1361 'tools', 'json_schema_compiler', 'idl_schema.py')
1362 process = input_api.subprocess.Popen(
1363 [input_api.python_executable, idl_schema],
1364 stdin=input_api.subprocess.PIPE,
1365 stdout=input_api.subprocess.PIPE,
1366 stderr=input_api.subprocess.PIPE,
1367 universal_newlines=True)
1368 (_, error) = process.communicate(input=contents)
1369 return error or None
1370 except ValueError as e:
1371 return e
1372
1373
1374def _CheckParseErrors(input_api, output_api):
1375 """Check that IDL and JSON files do not contain syntax errors."""
1376 actions = {
1377 '.idl': _GetIDLParseError,
1378 '.json': _GetJSONParseError,
1379 }
1380 # These paths contain test data and other known invalid JSON files.
1381 excluded_patterns = [
joaodasilva718f87672014-08-30 09:25:491382 r'test[\\\/]data[\\\/]',
1383 r'^components[\\\/]policy[\\\/]resources[\\\/]policy_templates\.json$',
[email protected]99171a92014-06-03 08:44:471384 ]
1385 # Most JSON files are preprocessed and support comments, but these do not.
1386 json_no_comments_patterns = [
joaodasilva718f87672014-08-30 09:25:491387 r'^testing[\\\/]',
[email protected]99171a92014-06-03 08:44:471388 ]
1389 # Only run IDL checker on files in these directories.
1390 idl_included_patterns = [
joaodasilva718f87672014-08-30 09:25:491391 r'^chrome[\\\/]common[\\\/]extensions[\\\/]api[\\\/]',
1392 r'^extensions[\\\/]common[\\\/]api[\\\/]',
[email protected]99171a92014-06-03 08:44:471393 ]
1394
1395 def get_action(affected_file):
1396 filename = affected_file.LocalPath()
1397 return actions.get(input_api.os_path.splitext(filename)[1])
1398
1399 def MatchesFile(patterns, path):
1400 for pattern in patterns:
1401 if input_api.re.search(pattern, path):
1402 return True
1403 return False
1404
1405 def FilterFile(affected_file):
1406 action = get_action(affected_file)
1407 if not action:
1408 return False
1409 path = affected_file.LocalPath()
1410
1411 if MatchesFile(excluded_patterns, path):
1412 return False
1413
1414 if (action == _GetIDLParseError and
1415 not MatchesFile(idl_included_patterns, path)):
1416 return False
1417 return True
1418
1419 results = []
1420 for affected_file in input_api.AffectedFiles(
1421 file_filter=FilterFile, include_deletes=False):
1422 action = get_action(affected_file)
1423 kwargs = {}
1424 if (action == _GetJSONParseError and
1425 MatchesFile(json_no_comments_patterns, affected_file.LocalPath())):
1426 kwargs['eat_comments'] = False
1427 parse_error = action(input_api,
1428 affected_file.AbsoluteLocalPath(),
1429 **kwargs)
1430 if parse_error:
1431 results.append(output_api.PresubmitError('%s could not be parsed: %s' %
1432 (affected_file.LocalPath(), parse_error)))
1433 return results
1434
1435
[email protected]760deea2013-12-10 19:33:491436def _CheckJavaStyle(input_api, output_api):
1437 """Runs checkstyle on changed java files and returns errors if any exist."""
mohan.reddyf21db962014-10-16 12:26:471438 import sys
[email protected]760deea2013-12-10 19:33:491439 original_sys_path = sys.path
1440 try:
1441 sys.path = sys.path + [input_api.os_path.join(
1442 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkstyle')]
1443 import checkstyle
1444 finally:
1445 # Restore sys.path to what it was before.
1446 sys.path = original_sys_path
1447
1448 return checkstyle.RunCheckstyle(
davileen72d76532015-01-20 22:30:091449 input_api, output_api, 'tools/android/checkstyle/chromium-style-5.0.xml',
newtd8b7d30e92015-01-23 18:10:511450 black_list=_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
[email protected]760deea2013-12-10 19:33:491451
1452
dchenge07de812016-06-20 19:27:171453def _CheckIpcOwners(input_api, output_api):
1454 """Checks that affected files involving IPC have an IPC OWNERS rule.
1455
1456 Whether or not a file affects IPC is determined by a simple whitelist of
1457 filename patterns."""
1458 file_patterns = [
1459 '*_messages.cc',
1460 '*_messages*.h',
1461 '*_param_traits*.*',
1462 '*.mojom',
1463 '*_struct_traits*.*',
1464 '*_type_converter*.*',
1465 # Blink uses a different file naming convention
1466 '*StructTraits*.*',
1467 '*TypeConverter*.*',
1468 ]
1469
scottmg7a6ed5ba2016-11-04 18:22:041470 # These third_party directories do not contain IPCs, but contain files
1471 # matching the above patterns, which trigger false positives.
1472 exclude_paths = [
1473 'third_party/crashpad/*',
1474 ]
1475
dchenge07de812016-06-20 19:27:171476 # Dictionary mapping an OWNERS file path to Patterns.
1477 # Patterns is a dictionary mapping glob patterns (suitable for use in per-file
1478 # rules ) to a PatternEntry.
1479 # PatternEntry is a dictionary with two keys:
1480 # - 'files': the files that are matched by this pattern
1481 # - 'rules': the per-file rules needed for this pattern
1482 # For example, if we expect OWNERS file to contain rules for *.mojom and
1483 # *_struct_traits*.*, Patterns might look like this:
1484 # {
1485 # '*.mojom': {
1486 # 'files': ...,
1487 # 'rules': [
1488 # 'per-file *.mojom=set noparent',
1489 # 'per-file *.mojom=file://ipc/SECURITY_OWNERS',
1490 # ],
1491 # },
1492 # '*_struct_traits*.*': {
1493 # 'files': ...,
1494 # 'rules': [
1495 # 'per-file *_struct_traits*.*=set noparent',
1496 # 'per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS',
1497 # ],
1498 # },
1499 # }
1500 to_check = {}
1501
1502 # Iterate through the affected files to see what we actually need to check
1503 # for. We should only nag patch authors about per-file rules if a file in that
1504 # directory would match that pattern. If a directory only contains *.mojom
1505 # files and no *_messages*.h files, we should only nag about rules for
1506 # *.mojom files.
rockot51249332016-06-23 16:32:251507 for f in input_api.change.AffectedFiles(include_deletes=False):
dchenge07de812016-06-20 19:27:171508 for pattern in file_patterns:
1509 if input_api.fnmatch.fnmatch(
1510 input_api.os_path.basename(f.LocalPath()), pattern):
scottmg7a6ed5ba2016-11-04 18:22:041511 skip = False
1512 for exclude in exclude_paths:
1513 if input_api.fnmatch.fnmatch(f.LocalPath(), exclude):
1514 skip = True
1515 break
1516 if skip:
1517 continue
dchenge07de812016-06-20 19:27:171518 owners_file = input_api.os_path.join(
1519 input_api.os_path.dirname(f.LocalPath()), 'OWNERS')
1520 if owners_file not in to_check:
1521 to_check[owners_file] = {}
1522 if pattern not in to_check[owners_file]:
1523 to_check[owners_file][pattern] = {
1524 'files': [],
1525 'rules': [
1526 'per-file %s=set noparent' % pattern,
1527 'per-file %s=file://ipc/SECURITY_OWNERS' % pattern,
1528 ]
1529 }
1530 to_check[owners_file][pattern]['files'].append(f)
1531 break
1532
1533 # Now go through the OWNERS files we collected, filtering out rules that are
1534 # already present in that OWNERS file.
1535 for owners_file, patterns in to_check.iteritems():
1536 try:
1537 with file(owners_file) as f:
1538 lines = set(f.read().splitlines())
1539 for entry in patterns.itervalues():
1540 entry['rules'] = [rule for rule in entry['rules'] if rule not in lines
1541 ]
1542 except IOError:
1543 # No OWNERS file, so all the rules are definitely missing.
1544 continue
1545
1546 # All the remaining lines weren't found in OWNERS files, so emit an error.
1547 errors = []
1548 for owners_file, patterns in to_check.iteritems():
1549 missing_lines = []
1550 files = []
1551 for pattern, entry in patterns.iteritems():
1552 missing_lines.extend(entry['rules'])
1553 files.extend([' %s' % f.LocalPath() for f in entry['files']])
1554 if missing_lines:
1555 errors.append(
1556 '%s is missing the following lines:\n\n%s\n\nfor changed files:\n%s' %
1557 (owners_file, '\n'.join(missing_lines), '\n'.join(files)))
1558
1559 results = []
1560 if errors:
vabrf5ce3bf92016-07-11 14:52:411561 if input_api.is_committing:
1562 output = output_api.PresubmitError
1563 else:
1564 output = output_api.PresubmitPromptWarning
1565 results.append(output(
dchenge07de812016-06-20 19:27:171566 'Found changes to IPC files without a security OWNER!',
1567 long_text='\n\n'.join(errors)))
1568
1569 return results
1570
1571
jbriance9e12f162016-11-25 07:57:501572def _CheckUselessForwardDeclarations(input_api, output_api):
jbriance2c51e821a2016-12-12 08:24:311573 """Checks that added or removed lines in non third party affected
1574 header files do not lead to new useless class or struct forward
1575 declaration.
jbriance9e12f162016-11-25 07:57:501576 """
1577 results = []
1578 class_pattern = input_api.re.compile(r'^class\s+(\w+);$',
1579 input_api.re.MULTILINE)
1580 struct_pattern = input_api.re.compile(r'^struct\s+(\w+);$',
1581 input_api.re.MULTILINE)
1582 for f in input_api.AffectedFiles(include_deletes=False):
jbriance2c51e821a2016-12-12 08:24:311583 if (f.LocalPath().startswith('third_party') and
1584 not f.LocalPath().startswith('third_party/WebKit') and
1585 not f.LocalPath().startswith('third_party\\WebKit')):
1586 continue
1587
jbriance9e12f162016-11-25 07:57:501588 if not f.LocalPath().endswith('.h'):
1589 continue
1590
1591 contents = input_api.ReadFile(f)
1592 fwd_decls = input_api.re.findall(class_pattern, contents)
1593 fwd_decls.extend(input_api.re.findall(struct_pattern, contents))
1594
1595 useless_fwd_decls = []
1596 for decl in fwd_decls:
1597 count = sum(1 for _ in input_api.re.finditer(
1598 r'\b%s\b' % input_api.re.escape(decl), contents))
1599 if count == 1:
1600 useless_fwd_decls.append(decl)
1601
1602 if not useless_fwd_decls:
1603 continue
1604
1605 for line in f.GenerateScmDiff().splitlines():
1606 if (line.startswith('-') and not line.startswith('--') or
1607 line.startswith('+') and not line.startswith('++')):
1608 for decl in useless_fwd_decls:
1609 if input_api.re.search(r'\b%s\b' % decl, line[1:]):
1610 results.append(output_api.PresubmitPromptWarning(
1611 '%s: %s forward declaration is becoming useless' %
1612 (f.LocalPath(), decl)))
1613 useless_fwd_decls.remove(decl)
1614
1615 return results
1616
1617
dskiba88634f4e2015-08-14 23:03:291618def _CheckAndroidToastUsage(input_api, output_api):
1619 """Checks that code uses org.chromium.ui.widget.Toast instead of
1620 android.widget.Toast (Chromium Toast doesn't force hardware
1621 acceleration on low-end devices, saving memory).
1622 """
1623 toast_import_pattern = input_api.re.compile(
1624 r'^import android\.widget\.Toast;$')
1625
1626 errors = []
1627
1628 sources = lambda affected_file: input_api.FilterSourceFile(
1629 affected_file,
1630 black_list=(_EXCLUDED_PATHS +
1631 _TEST_CODE_EXCLUDED_PATHS +
1632 input_api.DEFAULT_BLACK_LIST +
1633 (r'^chromecast[\\\/].*',
1634 r'^remoting[\\\/].*')),
1635 white_list=(r'.*\.java$',))
1636
1637 for f in input_api.AffectedSourceFiles(sources):
1638 for line_num, line in f.ChangedContents():
1639 if toast_import_pattern.search(line):
1640 errors.append("%s:%d" % (f.LocalPath(), line_num))
1641
1642 results = []
1643
1644 if errors:
1645 results.append(output_api.PresubmitError(
1646 'android.widget.Toast usage is detected. Android toasts use hardware'
1647 ' acceleration, and can be\ncostly on low-end devices. Please use'
1648 ' org.chromium.ui.widget.Toast instead.\n'
1649 'Contact [email protected] if you have any questions.',
1650 errors))
1651
1652 return results
1653
1654
dgnaa68d5e2015-06-10 10:08:221655def _CheckAndroidCrLogUsage(input_api, output_api):
1656 """Checks that new logs using org.chromium.base.Log:
1657 - Are using 'TAG' as variable name for the tags (warn)
dgn38736db2015-09-18 19:20:511658 - Are using a tag that is shorter than 20 characters (error)
dgnaa68d5e2015-06-10 10:08:221659 """
pkotwicza1dd0b002016-05-16 14:41:041660
1661 # Do not check format of logs in //chrome/android/webapk because
1662 # //chrome/android/webapk cannot depend on //base
1663 cr_log_check_excluded_paths = [
1664 r"^chrome[\\\/]android[\\\/]webapk[\\\/].*",
1665 ]
1666
dgnaa68d5e2015-06-10 10:08:221667 cr_log_import_pattern = input_api.re.compile(
dgn87d9fb62015-06-12 09:15:121668 r'^import org\.chromium\.base\.Log;$', input_api.re.MULTILINE)
1669 class_in_base_pattern = input_api.re.compile(
1670 r'^package org\.chromium\.base;$', input_api.re.MULTILINE)
1671 has_some_log_import_pattern = input_api.re.compile(
1672 r'^import .*\.Log;$', input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221673 # Extract the tag from lines like `Log.d(TAG, "*");` or `Log.d("TAG", "*");`
dgn87d9fb62015-06-12 09:15:121674 log_call_pattern = input_api.re.compile(r'^\s*Log\.\w\((?P<tag>\"?\w+\"?)\,')
dgnaa68d5e2015-06-10 10:08:221675 log_decl_pattern = input_api.re.compile(
dgn38736db2015-09-18 19:20:511676 r'^\s*private static final String TAG = "(?P<name>(.*))";',
dgnaa68d5e2015-06-10 10:08:221677 input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221678
Vincent Scheib16d7b272015-09-15 18:09:071679 REF_MSG = ('See docs/android_logging.md '
dgnaa68d5e2015-06-10 10:08:221680 'or contact [email protected] for more info.')
pkotwicza1dd0b002016-05-16 14:41:041681 sources = lambda x: input_api.FilterSourceFile(x, white_list=(r'.*\.java$',),
1682 black_list=cr_log_check_excluded_paths)
dgn87d9fb62015-06-12 09:15:121683
dgnaa68d5e2015-06-10 10:08:221684 tag_decl_errors = []
1685 tag_length_errors = []
dgn87d9fb62015-06-12 09:15:121686 tag_errors = []
dgn38736db2015-09-18 19:20:511687 tag_with_dot_errors = []
dgn87d9fb62015-06-12 09:15:121688 util_log_errors = []
dgnaa68d5e2015-06-10 10:08:221689
1690 for f in input_api.AffectedSourceFiles(sources):
1691 file_content = input_api.ReadFile(f)
1692 has_modified_logs = False
1693
1694 # Per line checks
dgn87d9fb62015-06-12 09:15:121695 if (cr_log_import_pattern.search(file_content) or
1696 (class_in_base_pattern.search(file_content) and
1697 not has_some_log_import_pattern.search(file_content))):
1698 # Checks to run for files using cr log
dgnaa68d5e2015-06-10 10:08:221699 for line_num, line in f.ChangedContents():
1700
1701 # Check if the new line is doing some logging
dgn87d9fb62015-06-12 09:15:121702 match = log_call_pattern.search(line)
dgnaa68d5e2015-06-10 10:08:221703 if match:
1704 has_modified_logs = True
1705
1706 # Make sure it uses "TAG"
1707 if not match.group('tag') == 'TAG':
1708 tag_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgn87d9fb62015-06-12 09:15:121709 else:
1710 # Report non cr Log function calls in changed lines
1711 for line_num, line in f.ChangedContents():
1712 if log_call_pattern.search(line):
1713 util_log_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgnaa68d5e2015-06-10 10:08:221714
1715 # Per file checks
1716 if has_modified_logs:
1717 # Make sure the tag is using the "cr" prefix and is not too long
1718 match = log_decl_pattern.search(file_content)
dgn38736db2015-09-18 19:20:511719 tag_name = match.group('name') if match else None
1720 if not tag_name:
dgnaa68d5e2015-06-10 10:08:221721 tag_decl_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511722 elif len(tag_name) > 20:
dgnaa68d5e2015-06-10 10:08:221723 tag_length_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511724 elif '.' in tag_name:
1725 tag_with_dot_errors.append(f.LocalPath())
dgnaa68d5e2015-06-10 10:08:221726
1727 results = []
1728 if tag_decl_errors:
1729 results.append(output_api.PresubmitPromptWarning(
1730 'Please define your tags using the suggested format: .\n'
dgn38736db2015-09-18 19:20:511731 '"private static final String TAG = "<package tag>".\n'
1732 'They will be prepended with "cr_" automatically.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221733 tag_decl_errors))
1734
1735 if tag_length_errors:
1736 results.append(output_api.PresubmitError(
1737 'The tag length is restricted by the system to be at most '
dgn38736db2015-09-18 19:20:511738 '20 characters.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221739 tag_length_errors))
1740
1741 if tag_errors:
1742 results.append(output_api.PresubmitPromptWarning(
1743 'Please use a variable named "TAG" for your log tags.\n' + REF_MSG,
1744 tag_errors))
1745
dgn87d9fb62015-06-12 09:15:121746 if util_log_errors:
dgn4401aa52015-04-29 16:26:171747 results.append(output_api.PresubmitPromptWarning(
dgn87d9fb62015-06-12 09:15:121748 'Please use org.chromium.base.Log for new logs.\n' + REF_MSG,
1749 util_log_errors))
1750
dgn38736db2015-09-18 19:20:511751 if tag_with_dot_errors:
1752 results.append(output_api.PresubmitPromptWarning(
1753 'Dot in log tags cause them to be elided in crash reports.\n' + REF_MSG,
1754 tag_with_dot_errors))
1755
dgn4401aa52015-04-29 16:26:171756 return results
1757
1758
yolandyan45001472016-12-21 21:12:421759def _CheckAndroidTestAnnotationUsage(input_api, output_api):
1760 """Checks that android.test.suitebuilder.annotation.* is no longer used."""
1761 deprecated_annotation_import_pattern = input_api.re.compile(
1762 r'^import android\.test\.suitebuilder\.annotation\..*;',
1763 input_api.re.MULTILINE)
1764 sources = lambda x: input_api.FilterSourceFile(
1765 x, white_list=(r'.*\.java$',), black_list=None)
1766 errors = []
1767 for f in input_api.AffectedFiles(sources):
1768 for line_num, line in f.ChangedContents():
1769 if deprecated_annotation_import_pattern.search(line):
1770 errors.append("%s:%d" % (f.LocalPath(), line_num))
1771
1772 results = []
1773 if errors:
1774 results.append(output_api.PresubmitError(
1775 'Annotations in android.test.suitebuilder.annotation have been'
1776 ' deprecated since API level 24. Please use android.support.test.filters'
1777 ' from //third_party/android_support_test_runner:runner_java instead.'
1778 ' Contact [email protected] if you have any questions.', errors))
1779 return results
1780
1781
agrieve7b6479d82015-10-07 14:24:221782def _CheckAndroidNewMdpiAssetLocation(input_api, output_api):
1783 """Checks if MDPI assets are placed in a correct directory."""
1784 file_filter = lambda f: (f.LocalPath().endswith('.png') and
1785 ('/res/drawable/' in f.LocalPath() or
1786 '/res/drawable-ldrtl/' in f.LocalPath()))
1787 errors = []
1788 for f in input_api.AffectedFiles(include_deletes=False,
1789 file_filter=file_filter):
1790 errors.append(' %s' % f.LocalPath())
1791
1792 results = []
1793 if errors:
1794 results.append(output_api.PresubmitError(
1795 'MDPI assets should be placed in /res/drawable-mdpi/ or '
1796 '/res/drawable-ldrtl-mdpi/\ninstead of /res/drawable/ and'
1797 '/res/drawable-ldrtl/.\n'
1798 'Contact [email protected] if you have questions.', errors))
1799 return results
1800
1801
agrievef32bcc72016-04-04 14:57:401802class PydepsChecker(object):
1803 def __init__(self, input_api, pydeps_files):
1804 self._file_cache = {}
1805 self._input_api = input_api
1806 self._pydeps_files = pydeps_files
1807
1808 def _LoadFile(self, path):
1809 """Returns the list of paths within a .pydeps file relative to //."""
1810 if path not in self._file_cache:
1811 with open(path) as f:
1812 self._file_cache[path] = f.read()
1813 return self._file_cache[path]
1814
1815 def _ComputeNormalizedPydepsEntries(self, pydeps_path):
1816 """Returns an interable of paths within the .pydep, relativized to //."""
1817 os_path = self._input_api.os_path
1818 pydeps_dir = os_path.dirname(pydeps_path)
1819 entries = (l.rstrip() for l in self._LoadFile(pydeps_path).splitlines()
1820 if not l.startswith('*'))
1821 return (os_path.normpath(os_path.join(pydeps_dir, e)) for e in entries)
1822
1823 def _CreateFilesToPydepsMap(self):
1824 """Returns a map of local_path -> list_of_pydeps."""
1825 ret = {}
1826 for pydep_local_path in self._pydeps_files:
1827 for path in self._ComputeNormalizedPydepsEntries(pydep_local_path):
1828 ret.setdefault(path, []).append(pydep_local_path)
1829 return ret
1830
1831 def ComputeAffectedPydeps(self):
1832 """Returns an iterable of .pydeps files that might need regenerating."""
1833 affected_pydeps = set()
1834 file_to_pydeps_map = None
1835 for f in self._input_api.AffectedFiles(include_deletes=True):
1836 local_path = f.LocalPath()
1837 if local_path == 'DEPS':
1838 return self._pydeps_files
1839 elif local_path.endswith('.pydeps'):
1840 if local_path in self._pydeps_files:
1841 affected_pydeps.add(local_path)
1842 elif local_path.endswith('.py'):
1843 if file_to_pydeps_map is None:
1844 file_to_pydeps_map = self._CreateFilesToPydepsMap()
1845 affected_pydeps.update(file_to_pydeps_map.get(local_path, ()))
1846 return affected_pydeps
1847
1848 def DetermineIfStale(self, pydeps_path):
1849 """Runs print_python_deps.py to see if the files is stale."""
phajdan.jr0d9878552016-11-04 10:49:411850 import difflib
agrievef32bcc72016-04-04 14:57:401851 old_pydeps_data = self._LoadFile(pydeps_path).splitlines()
1852 cmd = old_pydeps_data[1][1:].strip()
1853 new_pydeps_data = self._input_api.subprocess.check_output(
1854 cmd + ' --output ""', shell=True)
phajdan.jr0d9878552016-11-04 10:49:411855 old_contents = old_pydeps_data[2:]
1856 new_contents = new_pydeps_data.splitlines()[2:]
agrievef32bcc72016-04-04 14:57:401857 if old_pydeps_data[2:] != new_pydeps_data.splitlines()[2:]:
phajdan.jr0d9878552016-11-04 10:49:411858 return cmd, '\n'.join(difflib.context_diff(old_contents, new_contents))
agrievef32bcc72016-04-04 14:57:401859
1860
1861def _CheckPydepsNeedsUpdating(input_api, output_api, checker_for_tests=None):
1862 """Checks if a .pydeps file needs to be regenerated."""
agrievebb9c5b472016-04-22 15:13:001863 # This check is mainly for Android, and involves paths not only in the
agrieve9bc4200b2016-05-04 16:33:281864 # PRESUBMIT.py, but also in the .pydeps files. It doesn't work on Windows and
1865 # Mac, so skip it on other platforms.
1866 if input_api.platform != 'linux2':
agrievebb9c5b472016-04-22 15:13:001867 return []
agrievef32bcc72016-04-04 14:57:401868 # TODO(agrieve): Update when there's a better way to detect this: crbug/570091
1869 is_android = input_api.os_path.exists('third_party/android_tools')
1870 pydeps_files = _ALL_PYDEPS_FILES if is_android else _GENERIC_PYDEPS_FILES
1871 results = []
1872 # First, check for new / deleted .pydeps.
1873 for f in input_api.AffectedFiles(include_deletes=True):
1874 if f.LocalPath().endswith('.pydeps'):
1875 if f.Action() == 'D' and f.LocalPath() in _ALL_PYDEPS_FILES:
1876 results.append(output_api.PresubmitError(
1877 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
1878 'remove %s' % f.LocalPath()))
1879 elif f.Action() != 'D' and f.LocalPath() not in _ALL_PYDEPS_FILES:
1880 results.append(output_api.PresubmitError(
1881 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
1882 'include %s' % f.LocalPath()))
1883
1884 if results:
1885 return results
1886
1887 checker = checker_for_tests or PydepsChecker(input_api, pydeps_files)
1888
1889 for pydep_path in checker.ComputeAffectedPydeps():
1890 try:
phajdan.jr0d9878552016-11-04 10:49:411891 result = checker.DetermineIfStale(pydep_path)
1892 if result:
1893 cmd, diff = result
agrievef32bcc72016-04-04 14:57:401894 results.append(output_api.PresubmitError(
phajdan.jr0d9878552016-11-04 10:49:411895 'File is stale: %s\nDiff (apply to fix):\n%s\n'
1896 'To regenerate, run:\n\n %s' %
1897 (pydep_path, diff, cmd)))
agrievef32bcc72016-04-04 14:57:401898 except input_api.subprocess.CalledProcessError as error:
1899 return [output_api.PresubmitError('Error running: %s' % error.cmd,
1900 long_text=error.output)]
1901
1902 return results
1903
1904
glidere61efad2015-02-18 17:39:431905def _CheckSingletonInHeaders(input_api, output_api):
1906 """Checks to make sure no header files have |Singleton<|."""
1907 def FileFilter(affected_file):
1908 # It's ok for base/memory/singleton.h to have |Singleton<|.
1909 black_list = (_EXCLUDED_PATHS +
1910 input_api.DEFAULT_BLACK_LIST +
1911 (r"^base[\\\/]memory[\\\/]singleton\.h$",))
1912 return input_api.FilterSourceFile(affected_file, black_list=black_list)
1913
sergeyu34d21222015-09-16 00:11:441914 pattern = input_api.re.compile(r'(?<!class\sbase::)Singleton\s*<')
glidere61efad2015-02-18 17:39:431915 files = []
1916 for f in input_api.AffectedSourceFiles(FileFilter):
1917 if (f.LocalPath().endswith('.h') or f.LocalPath().endswith('.hxx') or
1918 f.LocalPath().endswith('.hpp') or f.LocalPath().endswith('.inl')):
1919 contents = input_api.ReadFile(f)
1920 for line in contents.splitlines(False):
oysteinec430ad42015-10-22 20:55:241921 if (not line.lstrip().startswith('//') and # Strip C++ comment.
glidere61efad2015-02-18 17:39:431922 pattern.search(line)):
1923 files.append(f)
1924 break
1925
1926 if files:
yolandyandaabc6d2016-04-18 18:29:391927 return [output_api.PresubmitError(
sergeyu34d21222015-09-16 00:11:441928 'Found base::Singleton<T> in the following header files.\n' +
glidere61efad2015-02-18 17:39:431929 'Please move them to an appropriate source file so that the ' +
1930 'template gets instantiated in a single compilation unit.',
1931 files) ]
1932 return []
1933
1934
dbeam1ec68ac2016-12-15 05:22:241935def _CheckNoDeprecatedCompiledResourcesGyp(input_api, output_api):
dbeam37e8e7402016-02-10 22:58:201936 """Checks for old style compiled_resources.gyp files."""
1937 is_compiled_resource = lambda fp: fp.endswith('compiled_resources.gyp')
1938
1939 added_compiled_resources = filter(is_compiled_resource, [
1940 f.LocalPath() for f in input_api.AffectedFiles() if f.Action() == 'A'
1941 ])
1942
1943 if not added_compiled_resources:
1944 return []
1945
1946 return [output_api.PresubmitError(
1947 "Found new compiled_resources.gyp files:\n%s\n\n"
1948 "compiled_resources.gyp files are deprecated,\n"
michaelpgdb9985072016-02-24 19:13:551949 "please use compiled_resources2.gyp instead:\n"
1950 "https://chromium.googlesource.com/chromium/src/+/master/docs/closure_compilation.md"
1951 %
dbeam37e8e7402016-02-10 22:58:201952 "\n".join(added_compiled_resources))]
1953
1954
[email protected]fd20b902014-05-09 02:14:531955_DEPRECATED_CSS = [
1956 # Values
1957 ( "-webkit-box", "flex" ),
1958 ( "-webkit-inline-box", "inline-flex" ),
1959 ( "-webkit-flex", "flex" ),
1960 ( "-webkit-inline-flex", "inline-flex" ),
1961 ( "-webkit-min-content", "min-content" ),
1962 ( "-webkit-max-content", "max-content" ),
1963
1964 # Properties
1965 ( "-webkit-background-clip", "background-clip" ),
1966 ( "-webkit-background-origin", "background-origin" ),
1967 ( "-webkit-background-size", "background-size" ),
1968 ( "-webkit-box-shadow", "box-shadow" ),
1969
1970 # Functions
1971 ( "-webkit-gradient", "gradient" ),
1972 ( "-webkit-repeating-gradient", "repeating-gradient" ),
1973 ( "-webkit-linear-gradient", "linear-gradient" ),
1974 ( "-webkit-repeating-linear-gradient", "repeating-linear-gradient" ),
1975 ( "-webkit-radial-gradient", "radial-gradient" ),
1976 ( "-webkit-repeating-radial-gradient", "repeating-radial-gradient" ),
1977]
1978
dbeam1ec68ac2016-12-15 05:22:241979def _CheckNoDeprecatedCss(input_api, output_api):
[email protected]fd20b902014-05-09 02:14:531980 """ Make sure that we don't use deprecated CSS
[email protected]9a48e3f82014-05-22 00:06:251981 properties, functions or values. Our external
mdjonesae0286c32015-06-10 18:10:341982 documentation and iOS CSS for dom distiller
1983 (reader mode) are ignored by the hooks as it
[email protected]9a48e3f82014-05-22 00:06:251984 needs to be consumed by WebKit. """
[email protected]fd20b902014-05-09 02:14:531985 results = []
dbeam070cfe62014-10-22 06:44:021986 file_inclusion_pattern = (r".+\.css$",)
[email protected]9a48e3f82014-05-22 00:06:251987 black_list = (_EXCLUDED_PATHS +
1988 _TEST_CODE_EXCLUDED_PATHS +
1989 input_api.DEFAULT_BLACK_LIST +
1990 (r"^chrome/common/extensions/docs",
1991 r"^chrome/docs",
mdjonesae0286c32015-06-10 18:10:341992 r"^components/dom_distiller/core/css/distilledpage_ios.css",
sdefresneda218472015-12-07 18:38:051993 r"^components/flags_ui/resources/apple_flags.css",
sdefresne6308d7f2016-02-15 09:38:441994 r"^components/neterror/resources/neterror.css",
[email protected]9a48e3f82014-05-22 00:06:251995 r"^native_client_sdk"))
1996 file_filter = lambda f: input_api.FilterSourceFile(
1997 f, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]fd20b902014-05-09 02:14:531998 for fpath in input_api.AffectedFiles(file_filter=file_filter):
1999 for line_num, line in fpath.ChangedContents():
2000 for (deprecated_value, value) in _DEPRECATED_CSS:
dbeam070cfe62014-10-22 06:44:022001 if deprecated_value in line:
[email protected]fd20b902014-05-09 02:14:532002 results.append(output_api.PresubmitError(
2003 "%s:%d: Use of deprecated CSS %s, use %s instead" %
2004 (fpath.LocalPath(), line_num, deprecated_value, value)))
2005 return results
2006
mohan.reddyf21db962014-10-16 12:26:472007
dbeam070cfe62014-10-22 06:44:022008_DEPRECATED_JS = [
2009 ( "__lookupGetter__", "Object.getOwnPropertyDescriptor" ),
2010 ( "__defineGetter__", "Object.defineProperty" ),
2011 ( "__defineSetter__", "Object.defineProperty" ),
2012]
2013
dbeam1ec68ac2016-12-15 05:22:242014def _CheckNoDeprecatedJs(input_api, output_api):
dbeam070cfe62014-10-22 06:44:022015 """Make sure that we don't use deprecated JS in Chrome code."""
2016 results = []
2017 file_inclusion_pattern = (r".+\.js$",) # TODO(dbeam): .html?
2018 black_list = (_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
2019 input_api.DEFAULT_BLACK_LIST)
2020 file_filter = lambda f: input_api.FilterSourceFile(
2021 f, white_list=file_inclusion_pattern, black_list=black_list)
2022 for fpath in input_api.AffectedFiles(file_filter=file_filter):
2023 for lnum, line in fpath.ChangedContents():
2024 for (deprecated, replacement) in _DEPRECATED_JS:
2025 if deprecated in line:
2026 results.append(output_api.PresubmitError(
2027 "%s:%d: Use of deprecated JS %s, use %s instead" %
2028 (fpath.LocalPath(), lnum, deprecated, replacement)))
2029 return results
2030
2031
dbeam1ec68ac2016-12-15 05:22:242032def _CheckForRiskyJsFeatures(input_api, output_api):
2033 maybe_ios_js = (r"^(ios|components|ui\/webui\/resources)\/.+\.js$", )
2034 file_filter = lambda f: input_api.FilterSourceFile(f, white_list=maybe_ios_js)
2035
2036 arrow_lines = []
2037 for f in input_api.AffectedFiles(file_filter=file_filter):
2038 for lnum, line in f.ChangedContents():
2039 if ' => ' in line:
2040 arrow_lines.append((f.LocalPath(), lnum))
2041
2042 if not arrow_lines:
2043 return []
2044
2045 return [output_api.PresubmitPromptWarning("""
2046Use of => operator detected in:
2047%s
2048Please ensure your code does not run on iOS9 (=> (arrow) does not work there).
2049https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#Arrow-Functions
2050""" % "\n".join(" %s:%d\n" % line for line in arrow_lines))]
2051
2052
dgnaa68d5e2015-06-10 10:08:222053def _AndroidSpecificOnUploadChecks(input_api, output_api):
2054 """Groups checks that target android code."""
2055 results = []
dgnaa68d5e2015-06-10 10:08:222056 results.extend(_CheckAndroidCrLogUsage(input_api, output_api))
agrieve7b6479d82015-10-07 14:24:222057 results.extend(_CheckAndroidNewMdpiAssetLocation(input_api, output_api))
dskiba88634f4e2015-08-14 23:03:292058 results.extend(_CheckAndroidToastUsage(input_api, output_api))
yolandyan45001472016-12-21 21:12:422059 results.extend(_CheckAndroidTestAnnotationUsage(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:222060 return results
2061
2062
[email protected]22c9bd72011-03-27 16:47:392063def _CommonChecks(input_api, output_api):
2064 """Checks common to both upload and commit."""
2065 results = []
2066 results.extend(input_api.canned_checks.PanProjectChecks(
[email protected]3de922f2013-12-20 13:27:382067 input_api, output_api,
qyearsleyfa2cfcf82016-12-15 18:03:542068 excluded_paths=_EXCLUDED_PATHS))
machenbachfbda9b72016-12-06 13:13:582069 results.extend(
2070 input_api.canned_checks.CheckAuthorizedAuthor(input_api, output_api))
[email protected]55459852011-08-10 15:17:192071 results.extend(
[email protected]760deea2013-12-10 19:33:492072 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api))
[email protected]10689ca2011-09-02 02:31:542073 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
[email protected]72df4e782012-06-21 16:28:182074 results.extend(_CheckNoUNIT_TESTInSourceFiles(input_api, output_api))
danakj61c1aa22015-10-26 19:55:522075 results.extend(_CheckDCHECK_IS_ONHasBraces(input_api, output_api))
[email protected]8ea5d4b2011-09-13 21:49:222076 results.extend(_CheckNoNewWStrings(input_api, output_api))
[email protected]2a8ac9c2011-10-19 17:20:442077 results.extend(_CheckNoDEPSGIT(input_api, output_api))
[email protected]127f18ec2012-06-16 05:05:592078 results.extend(_CheckNoBannedFunctions(input_api, output_api))
[email protected]6c063c62012-07-11 19:11:062079 results.extend(_CheckNoPragmaOnce(input_api, output_api))
[email protected]e7479052012-09-19 00:26:122080 results.extend(_CheckNoTrinaryTrueFalse(input_api, output_api))
[email protected]55f9f382012-07-31 11:02:182081 results.extend(_CheckUnwantedDependencies(input_api, output_api))
[email protected]fbcafe5a2012-08-08 15:31:222082 results.extend(_CheckFilePermissions(input_api, output_api))
robertocn832f5992017-01-04 19:01:302083 results.extend(_CheckTeamTags(input_api, output_api))
[email protected]c8278b32012-10-30 20:35:492084 results.extend(_CheckNoAuraWindowPropertyHInHeaders(input_api, output_api))
[email protected]2309b0fa02012-11-16 12:18:272085 results.extend(_CheckIncludeOrder(input_api, output_api))
[email protected]70ca77752012-11-20 03:45:032086 results.extend(_CheckForVersionControlConflicts(input_api, output_api))
[email protected]b8079ae4a2012-12-05 19:56:492087 results.extend(_CheckPatchFiles(input_api, output_api))
[email protected]06e6d0ff2012-12-11 01:36:442088 results.extend(_CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api))
[email protected]d2530012013-01-25 16:39:272089 results.extend(_CheckNoAbbreviationInPngFileName(input_api, output_api))
[email protected]b00342e7f2013-03-26 16:21:542090 results.extend(_CheckForInvalidOSMacros(input_api, output_api))
lliabraa35bab3932014-10-01 12:16:442091 results.extend(_CheckForInvalidIfDefinedMacros(input_api, output_api))
yolandyandaabc6d2016-04-18 18:29:392092 results.extend(_CheckFlakyTestUsage(input_api, output_api))
[email protected]e871964c2013-05-13 14:14:552093 results.extend(_CheckAddedDepsHaveTargetApprovals(input_api, output_api))
[email protected]9f919cc2013-07-31 03:04:042094 results.extend(
2095 input_api.canned_checks.CheckChangeHasNoTabs(
2096 input_api,
2097 output_api,
2098 source_file_filter=lambda x: x.LocalPath().endswith('.grd')))
[email protected]85218562013-11-22 07:41:402099 results.extend(_CheckSpamLogging(input_api, output_api))
[email protected]49aa76a2013-12-04 06:59:162100 results.extend(_CheckForAnonymousVariables(input_api, output_api))
[email protected]5fe0f8742013-11-29 01:04:592101 results.extend(_CheckCygwinShell(input_api, output_api))
[email protected]999261d2014-03-03 20:08:082102 results.extend(_CheckUserActionUpdate(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:242103 results.extend(_CheckNoDeprecatedCss(input_api, output_api))
2104 results.extend(_CheckNoDeprecatedJs(input_api, output_api))
[email protected]99171a92014-06-03 08:44:472105 results.extend(_CheckParseErrors(input_api, output_api))
mlamouria82272622014-09-16 18:45:042106 results.extend(_CheckForIPCRules(input_api, output_api))
mostynbb639aca52015-01-07 20:31:232107 results.extend(_CheckForWindowsLineEndings(input_api, output_api))
glidere61efad2015-02-18 17:39:432108 results.extend(_CheckSingletonInHeaders(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:242109 results.extend(_CheckNoDeprecatedCompiledResourcesGyp(input_api, output_api))
agrievef32bcc72016-04-04 14:57:402110 results.extend(_CheckPydepsNeedsUpdating(input_api, output_api))
wnwenbdc444e2016-05-25 13:44:152111 results.extend(_CheckJavaStyle(input_api, output_api))
dchenge07de812016-06-20 19:27:172112 results.extend(_CheckIpcOwners(input_api, output_api))
jbriance9e12f162016-11-25 07:57:502113 results.extend(_CheckUselessForwardDeclarations(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:242114 results.extend(_CheckForRiskyJsFeatures(input_api, output_api))
[email protected]2299dcf2012-11-15 19:56:242115
2116 if any('PRESUBMIT.py' == f.LocalPath() for f in input_api.AffectedFiles()):
2117 results.extend(input_api.canned_checks.RunUnitTestsInDirectory(
2118 input_api, output_api,
2119 input_api.PresubmitLocalPath(),
[email protected]6be63382013-01-21 15:42:382120 whitelist=[r'^PRESUBMIT_test\.py$']))
[email protected]22c9bd72011-03-27 16:47:392121 return results
[email protected]1f7b4172010-01-28 01:17:342122
[email protected]b337cb5b2011-01-23 21:24:052123
[email protected]b8079ae4a2012-12-05 19:56:492124def _CheckPatchFiles(input_api, output_api):
2125 problems = [f.LocalPath() for f in input_api.AffectedFiles()
2126 if f.LocalPath().endswith(('.orig', '.rej'))]
2127 if problems:
2128 return [output_api.PresubmitError(
2129 "Don't commit .rej and .orig files.", problems)]
[email protected]2fdd1f362013-01-16 03:56:032130 else:
2131 return []
[email protected]b8079ae4a2012-12-05 19:56:492132
2133
[email protected]b00342e7f2013-03-26 16:21:542134def _DidYouMeanOSMacro(bad_macro):
2135 try:
2136 return {'A': 'OS_ANDROID',
2137 'B': 'OS_BSD',
2138 'C': 'OS_CHROMEOS',
2139 'F': 'OS_FREEBSD',
2140 'L': 'OS_LINUX',
2141 'M': 'OS_MACOSX',
2142 'N': 'OS_NACL',
2143 'O': 'OS_OPENBSD',
2144 'P': 'OS_POSIX',
2145 'S': 'OS_SOLARIS',
2146 'W': 'OS_WIN'}[bad_macro[3].upper()]
2147 except KeyError:
2148 return ''
2149
2150
2151def _CheckForInvalidOSMacrosInFile(input_api, f):
2152 """Check for sensible looking, totally invalid OS macros."""
2153 preprocessor_statement = input_api.re.compile(r'^\s*#')
2154 os_macro = input_api.re.compile(r'defined\((OS_[^)]+)\)')
2155 results = []
2156 for lnum, line in f.ChangedContents():
2157 if preprocessor_statement.search(line):
2158 for match in os_macro.finditer(line):
2159 if not match.group(1) in _VALID_OS_MACROS:
2160 good = _DidYouMeanOSMacro(match.group(1))
2161 did_you_mean = ' (did you mean %s?)' % good if good else ''
2162 results.append(' %s:%d %s%s' % (f.LocalPath(),
2163 lnum,
2164 match.group(1),
2165 did_you_mean))
2166 return results
2167
2168
2169def _CheckForInvalidOSMacros(input_api, output_api):
2170 """Check all affected files for invalid OS macros."""
2171 bad_macros = []
2172 for f in input_api.AffectedFiles():
ellyjones47654342016-05-06 15:50:472173 if not f.LocalPath().endswith(('.py', '.js', '.html', '.css', '.md')):
[email protected]b00342e7f2013-03-26 16:21:542174 bad_macros.extend(_CheckForInvalidOSMacrosInFile(input_api, f))
2175
2176 if not bad_macros:
2177 return []
2178
2179 return [output_api.PresubmitError(
2180 'Possibly invalid OS macro[s] found. Please fix your code\n'
2181 'or add your macro to src/PRESUBMIT.py.', bad_macros)]
2182
lliabraa35bab3932014-10-01 12:16:442183
2184def _CheckForInvalidIfDefinedMacrosInFile(input_api, f):
2185 """Check all affected files for invalid "if defined" macros."""
2186 ALWAYS_DEFINED_MACROS = (
2187 "TARGET_CPU_PPC",
2188 "TARGET_CPU_PPC64",
2189 "TARGET_CPU_68K",
2190 "TARGET_CPU_X86",
2191 "TARGET_CPU_ARM",
2192 "TARGET_CPU_MIPS",
2193 "TARGET_CPU_SPARC",
2194 "TARGET_CPU_ALPHA",
2195 "TARGET_IPHONE_SIMULATOR",
2196 "TARGET_OS_EMBEDDED",
2197 "TARGET_OS_IPHONE",
2198 "TARGET_OS_MAC",
2199 "TARGET_OS_UNIX",
2200 "TARGET_OS_WIN32",
2201 )
2202 ifdef_macro = input_api.re.compile(r'^\s*#.*(?:ifdef\s|defined\()([^\s\)]+)')
2203 results = []
2204 for lnum, line in f.ChangedContents():
2205 for match in ifdef_macro.finditer(line):
2206 if match.group(1) in ALWAYS_DEFINED_MACROS:
2207 always_defined = ' %s is always defined. ' % match.group(1)
2208 did_you_mean = 'Did you mean \'#if %s\'?' % match.group(1)
2209 results.append(' %s:%d %s\n\t%s' % (f.LocalPath(),
2210 lnum,
2211 always_defined,
2212 did_you_mean))
2213 return results
2214
2215
2216def _CheckForInvalidIfDefinedMacros(input_api, output_api):
2217 """Check all affected files for invalid "if defined" macros."""
2218 bad_macros = []
2219 for f in input_api.AffectedFiles():
2220 if f.LocalPath().endswith(('.h', '.c', '.cc', '.m', '.mm')):
2221 bad_macros.extend(_CheckForInvalidIfDefinedMacrosInFile(input_api, f))
2222
2223 if not bad_macros:
2224 return []
2225
2226 return [output_api.PresubmitError(
2227 'Found ifdef check on always-defined macro[s]. Please fix your code\n'
2228 'or check the list of ALWAYS_DEFINED_MACROS in src/PRESUBMIT.py.',
2229 bad_macros)]
2230
2231
mlamouria82272622014-09-16 18:45:042232def _CheckForIPCRules(input_api, output_api):
2233 """Check for same IPC rules described in
2234 http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc
2235 """
2236 base_pattern = r'IPC_ENUM_TRAITS\('
2237 inclusion_pattern = input_api.re.compile(r'(%s)' % base_pattern)
2238 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_pattern)
2239
2240 problems = []
2241 for f in input_api.AffectedSourceFiles(None):
2242 local_path = f.LocalPath()
2243 if not local_path.endswith('.h'):
2244 continue
2245 for line_number, line in f.ChangedContents():
2246 if inclusion_pattern.search(line) and not comment_pattern.search(line):
2247 problems.append(
2248 '%s:%d\n %s' % (local_path, line_number, line.strip()))
2249
2250 if problems:
2251 return [output_api.PresubmitPromptWarning(
2252 _IPC_ENUM_TRAITS_DEPRECATED, problems)]
2253 else:
2254 return []
2255
[email protected]b00342e7f2013-03-26 16:21:542256
mostynbb639aca52015-01-07 20:31:232257def _CheckForWindowsLineEndings(input_api, output_api):
2258 """Check source code and known ascii text files for Windows style line
2259 endings.
2260 """
earthdok1b5e0ee2015-03-10 15:19:102261 known_text_files = r'.*\.(txt|html|htm|mhtml|py|gyp|gypi|gn|isolate)$'
mostynbb639aca52015-01-07 20:31:232262
2263 file_inclusion_pattern = (
2264 known_text_files,
2265 r'.+%s' % _IMPLEMENTATION_EXTENSIONS
2266 )
2267
2268 filter = lambda f: input_api.FilterSourceFile(
2269 f, white_list=file_inclusion_pattern, black_list=None)
2270 files = [f.LocalPath() for f in
2271 input_api.AffectedSourceFiles(filter)]
2272
2273 problems = []
2274
2275 for file in files:
2276 fp = open(file, 'r')
2277 for line in fp:
2278 if line.endswith('\r\n'):
2279 problems.append(file)
2280 break
2281 fp.close()
2282
2283 if problems:
2284 return [output_api.PresubmitPromptWarning('Are you sure that you want '
2285 'these files to contain Windows style line endings?\n' +
2286 '\n'.join(problems))]
2287
2288 return []
2289
2290
pastarmovj89f7ee12016-09-20 14:58:132291def _CheckSyslogUseWarning(input_api, output_api, source_file_filter=None,
2292 lint_filters=None, verbose_level=None):
2293 """Checks that all source files use SYSLOG properly."""
2294 syslog_files = []
2295 for f in input_api.AffectedSourceFiles(source_file_filter):
pastarmovj032ba5bc2017-01-12 10:41:562296 for line_number, line in f.ChangedContents():
2297 if 'SYSLOG' in line:
2298 syslog_files.append(f.LocalPath() + ':' + str(line_number))
2299
pastarmovj89f7ee12016-09-20 14:58:132300 if syslog_files:
2301 return [output_api.PresubmitPromptWarning(
2302 'Please make sure there are no privacy sensitive bits of data in SYSLOG'
2303 ' calls.\nFiles to check:\n', items=syslog_files)]
2304 return []
2305
2306
[email protected]1f7b4172010-01-28 01:17:342307def CheckChangeOnUpload(input_api, output_api):
2308 results = []
2309 results.extend(_CommonChecks(input_api, output_api))
tandriief664692014-09-23 14:51:472310 results.extend(_CheckValidHostsInDEPS(input_api, output_api))
scottmg39b29952014-12-08 18:31:282311 results.extend(
2312 input_api.canned_checks.CheckGNFormatted(input_api, output_api))
mcasasb7440c282015-02-04 14:52:192313 results.extend(_CheckUmaHistogramChanges(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:222314 results.extend(_AndroidSpecificOnUploadChecks(input_api, output_api))
pastarmovj89f7ee12016-09-20 14:58:132315 results.extend(_CheckSyslogUseWarning(input_api, output_api))
estadee17314a02017-01-12 16:22:162316 results.extend(_CheckGoogleSupportAnswerUrl(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542317 return results
[email protected]ca8d19842009-02-19 16:33:122318
2319
[email protected]1bfb8322014-04-23 01:02:412320def GetTryServerMasterForBot(bot):
2321 """Returns the Try Server master for the given bot.
2322
[email protected]0bb112362014-07-26 04:38:322323 It tries to guess the master from the bot name, but may still fail
2324 and return None. There is no longer a default master.
2325 """
2326 # Potentially ambiguous bot names are listed explicitly.
2327 master_map = {
tandriie5587792016-07-14 00:34:502328 'chromium_presubmit': 'master.tryserver.chromium.linux',
2329 'tools_build_presubmit': 'master.tryserver.chromium.linux',
[email protected]1bfb8322014-04-23 01:02:412330 }
[email protected]0bb112362014-07-26 04:38:322331 master = master_map.get(bot)
2332 if not master:
wnwen4fbaab82016-05-25 12:54:362333 if 'android' in bot:
tandriie5587792016-07-14 00:34:502334 master = 'master.tryserver.chromium.android'
wnwen4fbaab82016-05-25 12:54:362335 elif 'linux' in bot or 'presubmit' in bot:
tandriie5587792016-07-14 00:34:502336 master = 'master.tryserver.chromium.linux'
[email protected]0bb112362014-07-26 04:38:322337 elif 'win' in bot:
tandriie5587792016-07-14 00:34:502338 master = 'master.tryserver.chromium.win'
[email protected]0bb112362014-07-26 04:38:322339 elif 'mac' in bot or 'ios' in bot:
tandriie5587792016-07-14 00:34:502340 master = 'master.tryserver.chromium.mac'
[email protected]0bb112362014-07-26 04:38:322341 return master
[email protected]1bfb8322014-04-23 01:02:412342
2343
Paweł Hajdan, Jr55083782014-12-19 20:32:562344def GetDefaultTryConfigs(bots):
2345 """Returns a list of ('bot', set(['tests']), filtered by [bots].
[email protected]38c6a512013-12-18 23:48:012346 """
2347
Paweł Hajdan, Jr55083782014-12-19 20:32:562348 builders_and_tests = dict((bot, set(['defaulttests'])) for bot in bots)
[email protected]1bfb8322014-04-23 01:02:412349
2350 # Build up the mapping from tryserver master to bot/test.
2351 out = dict()
Paweł Hajdan, Jr55083782014-12-19 20:32:562352 for bot, tests in builders_and_tests.iteritems():
[email protected]1bfb8322014-04-23 01:02:412353 out.setdefault(GetTryServerMasterForBot(bot), {})[bot] = tests
2354 return out
[email protected]38c6a512013-12-18 23:48:012355
2356
[email protected]ca8d19842009-02-19 16:33:122357def CheckChangeOnCommit(input_api, output_api):
[email protected]fe5f57c52009-06-05 14:25:542358 results = []
[email protected]1f7b4172010-01-28 01:17:342359 results.extend(_CommonChecks(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542360 # Make sure the tree is 'open'.
[email protected]806e98e2010-03-19 17:49:272361 results.extend(input_api.canned_checks.CheckTreeIsOpen(
[email protected]7f238152009-08-12 19:00:342362 input_api,
2363 output_api,
[email protected]2fdd1f362013-01-16 03:56:032364 json_url='http://chromium-status.appspot.com/current?format=json'))
[email protected]806e98e2010-03-19 17:49:272365
[email protected]3e4eb112011-01-18 03:29:542366 results.extend(input_api.canned_checks.CheckChangeHasBugField(
2367 input_api, output_api))
[email protected]c4b47562011-12-05 23:39:412368 results.extend(input_api.canned_checks.CheckChangeHasDescription(
2369 input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542370 return results