blob: 8a7c75bbc30f6ffd4882e38cbebb39f4f1ff7375 [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",
[email protected]4306417642009-06-11 00:33:4026)
[email protected]ca8d19842009-02-19 16:33:1227
wnwenbdc444e2016-05-25 13:44:1528
jochen9ea8fdbc2014-09-25 13:21:3529# The NetscapePlugIn library is excluded from pan-project as it will soon
30# be deleted together with the rest of the NPAPI and it's not worthwhile to
31# update the coding style until then.
[email protected]3de922f2013-12-20 13:27:3832_TESTRUNNER_PATHS = (
[email protected]de28fed2e2014-02-01 14:36:3233 r"^content[\\\/]shell[\\\/]tools[\\\/]plugin[\\\/].*",
[email protected]3de922f2013-12-20 13:27:3834)
35
wnwenbdc444e2016-05-25 13:44:1536
[email protected]06e6d0ff2012-12-11 01:36:4437# Fragment of a regular expression that matches C++ and Objective-C++
38# implementation files.
39_IMPLEMENTATION_EXTENSIONS = r'\.(cc|cpp|cxx|mm)$'
40
wnwenbdc444e2016-05-25 13:44:1541
[email protected]06e6d0ff2012-12-11 01:36:4442# Regular expression that matches code only used for test binaries
43# (best effort).
44_TEST_CODE_EXCLUDED_PATHS = (
joaodasilva718f87672014-08-30 09:25:4945 r'.*[\\\/](fake_|test_|mock_).+%s' % _IMPLEMENTATION_EXTENSIONS,
[email protected]06e6d0ff2012-12-11 01:36:4446 r'.+_test_(base|support|util)%s' % _IMPLEMENTATION_EXTENSIONS,
[email protected]6e04f8c2014-01-29 18:08:3247 r'.+_(api|browser|kif|perf|pixel|unit|ui)?test(_[a-z]+)?%s' %
[email protected]e2d7e6f2013-04-23 12:57:1248 _IMPLEMENTATION_EXTENSIONS,
[email protected]06e6d0ff2012-12-11 01:36:4449 r'.+profile_sync_service_harness%s' % _IMPLEMENTATION_EXTENSIONS,
joaodasilva718f87672014-08-30 09:25:4950 r'.*[\\\/](test|tool(s)?)[\\\/].*',
[email protected]ef070cc2013-05-03 11:53:0551 # content_shell is used for running layout tests.
joaodasilva718f87672014-08-30 09:25:4952 r'content[\\\/]shell[\\\/].*',
[email protected]06e6d0ff2012-12-11 01:36:4453 # At request of folks maintaining this folder.
joaodasilva718f87672014-08-30 09:25:4954 r'chrome[\\\/]browser[\\\/]automation[\\\/].*',
[email protected]7b054982013-11-27 00:44:4755 # Non-production example code.
joaodasilva718f87672014-08-30 09:25:4956 r'mojo[\\\/]examples[\\\/].*',
[email protected]8176de12014-06-20 19:07:0857 # Launcher for running iOS tests on the simulator.
joaodasilva718f87672014-08-30 09:25:4958 r'testing[\\\/]iossim[\\\/]iossim\.mm$',
[email protected]06e6d0ff2012-12-11 01:36:4459)
[email protected]ca8d19842009-02-19 16:33:1260
wnwenbdc444e2016-05-25 13:44:1561
[email protected]eea609a2011-11-18 13:10:1262_TEST_ONLY_WARNING = (
63 'You might be calling functions intended only for testing from\n'
64 'production code. It is OK to ignore this warning if you know what\n'
65 'you are doing, as the heuristics used to detect the situation are\n'
[email protected]b0149772014-03-27 16:47:5866 'not perfect. The commit queue will not block on this warning.')
[email protected]eea609a2011-11-18 13:10:1267
68
[email protected]cf9b78f2012-11-14 11:40:2869_INCLUDE_ORDER_WARNING = (
marjaa017dc482015-03-09 17:13:4070 'Your #include order seems to be broken. Remember to use the right '
avice9a8982015-11-24 20:36:2171 'collation (LC_COLLATE=C) and check\nhttps://google.github.io/styleguide/'
72 'cppguide.html#Names_and_Order_of_Includes')
[email protected]cf9b78f2012-11-14 11:40:2873
wnwenbdc444e2016-05-25 13:44:1574
[email protected]127f18ec2012-06-16 05:05:5975_BANNED_OBJC_FUNCTIONS = (
76 (
77 'addTrackingRect:',
[email protected]23e6cbc2012-06-16 18:51:2078 (
79 'The use of -[NSView addTrackingRect:owner:userData:assumeInside:] is'
[email protected]127f18ec2012-06-16 05:05:5980 'prohibited. Please use CrTrackingArea instead.',
81 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
82 ),
83 False,
84 ),
85 (
[email protected]eaae1972014-04-16 04:17:2686 r'/NSTrackingArea\W',
[email protected]23e6cbc2012-06-16 18:51:2087 (
88 'The use of NSTrackingAreas is prohibited. Please use CrTrackingArea',
[email protected]127f18ec2012-06-16 05:05:5989 'instead.',
90 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
91 ),
92 False,
93 ),
94 (
95 'convertPointFromBase:',
[email protected]23e6cbc2012-06-16 18:51:2096 (
97 'The use of -[NSView convertPointFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:5998 'Please use |convertPoint:(point) fromView:nil| instead.',
99 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
100 ),
101 True,
102 ),
103 (
104 'convertPointToBase:',
[email protected]23e6cbc2012-06-16 18:51:20105 (
106 'The use of -[NSView convertPointToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59107 'Please use |convertPoint:(point) toView:nil| instead.',
108 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
109 ),
110 True,
111 ),
112 (
113 'convertRectFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20114 (
115 'The use of -[NSView convertRectFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59116 'Please use |convertRect:(point) fromView:nil| instead.',
117 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
118 ),
119 True,
120 ),
121 (
122 'convertRectToBase:',
[email protected]23e6cbc2012-06-16 18:51:20123 (
124 'The use of -[NSView convertRectToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59125 'Please use |convertRect:(point) toView:nil| instead.',
126 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
127 ),
128 True,
129 ),
130 (
131 'convertSizeFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20132 (
133 'The use of -[NSView convertSizeFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59134 'Please use |convertSize:(point) fromView:nil| instead.',
135 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
136 ),
137 True,
138 ),
139 (
140 'convertSizeToBase:',
[email protected]23e6cbc2012-06-16 18:51:20141 (
142 'The use of -[NSView convertSizeToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59143 'Please use |convertSize:(point) toView:nil| instead.',
144 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
145 ),
146 True,
147 ),
148)
149
150
151_BANNED_CPP_FUNCTIONS = (
[email protected]23e6cbc2012-06-16 18:51:20152 # Make sure that gtest's FRIEND_TEST() macro is not used; the
153 # FRIEND_TEST_ALL_PREFIXES() macro from base/gtest_prod_util.h should be
[email protected]e00ccc92012-11-01 17:32:30154 # used instead since that allows for FLAKY_ and DISABLED_ prefixes.
[email protected]23e6cbc2012-06-16 18:51:20155 (
156 'FRIEND_TEST(',
157 (
[email protected]e3c945502012-06-26 20:01:49158 'Chromium code should not use gtest\'s FRIEND_TEST() macro. Include',
[email protected]23e6cbc2012-06-16 18:51:20159 'base/gtest_prod_util.h and use FRIEND_TEST_ALL_PREFIXES() instead.',
160 ),
161 False,
[email protected]7345da02012-11-27 14:31:49162 (),
[email protected]23e6cbc2012-06-16 18:51:20163 ),
164 (
165 'ScopedAllowIO',
166 (
[email protected]e3c945502012-06-26 20:01:49167 'New code should not use ScopedAllowIO. Post a task to the blocking',
168 'pool or the FILE thread instead.',
[email protected]23e6cbc2012-06-16 18:51:20169 ),
[email protected]e3c945502012-06-26 20:01:49170 True,
[email protected]7345da02012-11-27 14:31:49171 (
nyad2c548b2015-12-09 03:22:32172 r"^base[\\\/]process[\\\/]process_linux\.cc$",
thestig75844fdb2014-09-09 19:47:10173 r"^base[\\\/]process[\\\/]process_metrics_linux\.cc$",
kmarshallbb619532016-01-29 21:24:49174 r"^blimp[\\\/]engine[\\\/]app[\\\/]blimp_browser_main_parts\.cc$",
tfarina0923ac52015-01-07 03:21:22175 r"^chrome[\\\/]browser[\\\/]chromeos[\\\/]boot_times_recorder\.cc$",
sky0e07a142016-03-25 21:27:31176 r"^chrome[\\\/]browser[\\\/]lifetime[\\\/]application_lifetime\.cc$",
alematee4016bb2014-11-12 17:38:51177 r"^chrome[\\\/]browser[\\\/]chromeos[\\\/]"
178 "customization_document_browsertest\.cc$",
philipj3f9d5bde2014-08-28 14:09:09179 r"^components[\\\/]crash[\\\/]app[\\\/]breakpad_mac\.mm$",
jochene9ba6dd2016-02-23 17:20:49180 r"^content[\\\/]shell[\\\/]browser[\\\/]layout_test[\\\/]" +
181 r"test_info_extractor\.cc$",
[email protected]de7d61ff2013-08-20 11:30:41182 r"^content[\\\/]shell[\\\/]browser[\\\/]shell_browser_main\.cc$",
183 r"^content[\\\/]shell[\\\/]browser[\\\/]shell_message_filter\.cc$",
jamesra03ae492014-10-03 04:26:48184 r"^mojo[\\\/]edk[\\\/]embedder[\\\/]" +
185 r"simple_platform_shared_buffer_posix\.cc$",
[email protected]398ad132013-04-02 15:11:01186 r"^net[\\\/]disk_cache[\\\/]cache_util\.cc$",
[email protected]1f52a572014-05-12 23:21:54187 r"^net[\\\/]url_request[\\\/]test_url_fetcher_factory\.cc$",
joedow91151042016-02-08 21:18:13188 r"^remoting[\\\/]host[\\\/]security_key[\\\/]"
189 "gnubby_auth_handler_linux\.cc$",
lambroslambrouf6fb94ea2016-06-27 21:21:53190 r"^ui[\\\/]base[\\\/]material_design[\\\/]"
191 "material_design_controller\.cc$",
kylechar16666242016-07-04 20:54:45192 r"^ui[\\\/]gl[\\\/]init[\\\/]gl_initializer_mac\.cc$",
193 r"^ui[\\\/]gl[\\\/]init[\\\/]gl_initializer_win\.cc$",
194 r"^ui[\\\/]gl[\\\/]init[\\\/]gl_initializer_x11\.cc$",
195 r"^ui[\\\/]ozone[\\\/]platform[\\\/]drm[\\\/]host[\\\/]"
196 "drm_display_host_manager\.cc$",
[email protected]7345da02012-11-27 14:31:49197 ),
[email protected]23e6cbc2012-06-16 18:51:20198 ),
[email protected]52657f62013-05-20 05:30:31199 (
tomhudsone2c14d552016-05-26 17:07:46200 'setMatrixClip',
201 (
202 'Overriding setMatrixClip() is prohibited; ',
203 'the base function is deprecated. ',
204 ),
205 True,
206 (),
207 ),
208 (
[email protected]52657f62013-05-20 05:30:31209 'SkRefPtr',
210 (
211 'The use of SkRefPtr is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22212 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31213 ),
214 True,
215 (),
216 ),
217 (
218 'SkAutoRef',
219 (
220 'The indirect use of SkRefPtr via SkAutoRef is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22221 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31222 ),
223 True,
224 (),
225 ),
226 (
227 'SkAutoTUnref',
228 (
229 'The use of SkAutoTUnref is dangerous because it implicitly ',
tomhudson7e6e0512016-04-19 19:27:22230 'converts to a raw pointer. Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31231 ),
232 True,
233 (),
234 ),
235 (
236 'SkAutoUnref',
237 (
238 'The indirect use of SkAutoTUnref through SkAutoUnref is dangerous ',
239 'because it implicitly converts to a raw pointer. ',
tomhudson7e6e0512016-04-19 19:27:22240 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31241 ),
242 True,
243 (),
244 ),
[email protected]d89eec82013-12-03 14:10:59245 (
246 r'/HANDLE_EINTR\(.*close',
247 (
248 'HANDLE_EINTR(close) is invalid. If close fails with EINTR, the file',
249 'descriptor will be closed, and it is incorrect to retry the close.',
250 'Either call close directly and ignore its return value, or wrap close',
251 'in IGNORE_EINTR to use its return value. See http://crbug.com/269623'
252 ),
253 True,
254 (),
255 ),
256 (
257 r'/IGNORE_EINTR\((?!.*close)',
258 (
259 'IGNORE_EINTR is only valid when wrapping close. To wrap other system',
260 'calls, use HANDLE_EINTR. See http://crbug.com/269623',
261 ),
262 True,
263 (
264 # Files that #define IGNORE_EINTR.
265 r'^base[\\\/]posix[\\\/]eintr_wrapper\.h$',
266 r'^ppapi[\\\/]tests[\\\/]test_broker\.cc$',
267 ),
268 ),
[email protected]ec5b3f02014-04-04 18:43:43269 (
270 r'/v8::Extension\(',
271 (
272 'Do not introduce new v8::Extensions into the code base, use',
273 'gin::Wrappable instead. See http://crbug.com/334679',
274 ),
275 True,
[email protected]f55c90ee62014-04-12 00:50:03276 (
joaodasilva718f87672014-08-30 09:25:49277 r'extensions[\\\/]renderer[\\\/]safe_builtins\.*',
[email protected]f55c90ee62014-04-12 00:50:03278 ),
[email protected]ec5b3f02014-04-04 18:43:43279 ),
skyostilf9469f72015-04-20 10:38:52280 (
sdefresneeaeccc52015-04-22 08:18:32281 '\<MessageLoopProxy\>',
skyostilf9469f72015-04-20 10:38:52282 (
283 'MessageLoopProxy is deprecated. ',
284 'Please use SingleThreadTaskRunner or ThreadTaskRunnerHandle instead.'
285 ),
286 True,
kinuko59024ce2015-04-21 22:18:30287 (
288 # Internal message_loop related code may still use it.
289 r'^base[\\\/]message_loop[\\\/].*',
290 ),
skyostilf9469f72015-04-20 10:38:52291 ),
jame2d1a952016-04-02 00:27:10292 (
293 '#pragma comment(lib,',
294 (
295 'Specify libraries to link with in build files and not in the source.',
296 ),
297 True,
298 (),
299 ),
[email protected]127f18ec2012-06-16 05:05:59300)
301
wnwenbdc444e2016-05-25 13:44:15302
mlamouria82272622014-09-16 18:45:04303_IPC_ENUM_TRAITS_DEPRECATED = (
304 'You are using IPC_ENUM_TRAITS() in your code. It has been deprecated.\n'
305 'See http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc')
306
[email protected]127f18ec2012-06-16 05:05:59307
[email protected]b00342e7f2013-03-26 16:21:54308_VALID_OS_MACROS = (
309 # Please keep sorted.
310 'OS_ANDROID',
311 'OS_BSD',
312 'OS_CAT', # For testing.
313 'OS_CHROMEOS',
314 'OS_FREEBSD',
315 'OS_IOS',
316 'OS_LINUX',
317 'OS_MACOSX',
318 'OS_NACL',
hidehikof7295f22014-10-28 11:57:21319 'OS_NACL_NONSFI',
320 'OS_NACL_SFI',
[email protected]b00342e7f2013-03-26 16:21:54321 'OS_OPENBSD',
322 'OS_POSIX',
[email protected]eda7afa12014-02-06 12:27:37323 'OS_QNX',
[email protected]b00342e7f2013-03-26 16:21:54324 'OS_SOLARIS',
[email protected]b00342e7f2013-03-26 16:21:54325 'OS_WIN',
326)
327
328
agrievef32bcc72016-04-04 14:57:40329_ANDROID_SPECIFIC_PYDEPS_FILES = [
330 'build/android/test_runner.pydeps',
agrieve732db3a2016-04-26 19:18:19331 'net/tools/testserver/testserver.pydeps',
agrievef32bcc72016-04-04 14:57:40332]
333
wnwenbdc444e2016-05-25 13:44:15334
agrievef32bcc72016-04-04 14:57:40335_GENERIC_PYDEPS_FILES = [
336 'build/secondary/tools/swarming_client/isolate.pydeps',
337]
338
wnwenbdc444e2016-05-25 13:44:15339
agrievef32bcc72016-04-04 14:57:40340_ALL_PYDEPS_FILES = _ANDROID_SPECIFIC_PYDEPS_FILES + _GENERIC_PYDEPS_FILES
341
342
[email protected]55459852011-08-10 15:17:19343def _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api):
344 """Attempts to prevent use of functions intended only for testing in
345 non-testing code. For now this is just a best-effort implementation
346 that ignores header files and may have some false positives. A
347 better implementation would probably need a proper C++ parser.
348 """
349 # We only scan .cc files and the like, as the declaration of
350 # for-testing functions in header files are hard to distinguish from
351 # calls to such functions without a proper C++ parser.
[email protected]06e6d0ff2012-12-11 01:36:44352 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
[email protected]55459852011-08-10 15:17:19353
jochenc0d4808c2015-07-27 09:25:42354 base_function_pattern = r'[ :]test::[^\s]+|ForTest(s|ing)?|for_test(s|ing)?'
[email protected]55459852011-08-10 15:17:19355 inclusion_pattern = input_api.re.compile(r'(%s)\s*\(' % base_function_pattern)
[email protected]23501822014-05-14 02:06:09356 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_function_pattern)
[email protected]55459852011-08-10 15:17:19357 exclusion_pattern = input_api.re.compile(
358 r'::[A-Za-z0-9_]+(%s)|(%s)[^;]+\{' % (
359 base_function_pattern, base_function_pattern))
360
361 def FilterFile(affected_file):
[email protected]06e6d0ff2012-12-11 01:36:44362 black_list = (_EXCLUDED_PATHS +
363 _TEST_CODE_EXCLUDED_PATHS +
364 input_api.DEFAULT_BLACK_LIST)
[email protected]55459852011-08-10 15:17:19365 return input_api.FilterSourceFile(
366 affected_file,
367 white_list=(file_inclusion_pattern, ),
368 black_list=black_list)
369
370 problems = []
371 for f in input_api.AffectedSourceFiles(FilterFile):
372 local_path = f.LocalPath()
[email protected]825d27182014-01-02 21:24:24373 for line_number, line in f.ChangedContents():
[email protected]2fdd1f362013-01-16 03:56:03374 if (inclusion_pattern.search(line) and
[email protected]de4f7d22013-05-23 14:27:46375 not comment_pattern.search(line) and
[email protected]2fdd1f362013-01-16 03:56:03376 not exclusion_pattern.search(line)):
[email protected]55459852011-08-10 15:17:19377 problems.append(
[email protected]2fdd1f362013-01-16 03:56:03378 '%s:%d\n %s' % (local_path, line_number, line.strip()))
[email protected]55459852011-08-10 15:17:19379
380 if problems:
[email protected]f7051d52013-04-02 18:31:42381 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
[email protected]2fdd1f362013-01-16 03:56:03382 else:
383 return []
[email protected]55459852011-08-10 15:17:19384
385
[email protected]10689ca2011-09-02 02:31:54386def _CheckNoIOStreamInHeaders(input_api, output_api):
387 """Checks to make sure no .h files include <iostream>."""
388 files = []
389 pattern = input_api.re.compile(r'^#include\s*<iostream>',
390 input_api.re.MULTILINE)
391 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
392 if not f.LocalPath().endswith('.h'):
393 continue
394 contents = input_api.ReadFile(f)
395 if pattern.search(contents):
396 files.append(f)
397
398 if len(files):
yolandyandaabc6d2016-04-18 18:29:39399 return [output_api.PresubmitError(
[email protected]6c063c62012-07-11 19:11:06400 'Do not #include <iostream> in header files, since it inserts static '
401 'initialization into every file including the header. Instead, '
[email protected]10689ca2011-09-02 02:31:54402 '#include <ostream>. See http://crbug.com/94794',
403 files) ]
404 return []
405
406
[email protected]72df4e782012-06-21 16:28:18407def _CheckNoUNIT_TESTInSourceFiles(input_api, output_api):
danakj61c1aa22015-10-26 19:55:52408 """Checks to make sure no source files use UNIT_TEST."""
[email protected]72df4e782012-06-21 16:28:18409 problems = []
410 for f in input_api.AffectedFiles():
411 if (not f.LocalPath().endswith(('.cc', '.mm'))):
412 continue
413
414 for line_num, line in f.ChangedContents():
[email protected]549f86a2013-11-19 13:00:04415 if 'UNIT_TEST ' in line or line.endswith('UNIT_TEST'):
[email protected]72df4e782012-06-21 16:28:18416 problems.append(' %s:%d' % (f.LocalPath(), line_num))
417
418 if not problems:
419 return []
420 return [output_api.PresubmitPromptWarning('UNIT_TEST is only for headers.\n' +
421 '\n'.join(problems))]
422
423
danakj61c1aa22015-10-26 19:55:52424def _CheckDCHECK_IS_ONHasBraces(input_api, output_api):
425 """Checks to make sure DCHECK_IS_ON() does not skip the braces."""
426 errors = []
427 pattern = input_api.re.compile(r'DCHECK_IS_ON(?!\(\))',
428 input_api.re.MULTILINE)
429 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
430 if (not f.LocalPath().endswith(('.cc', '.mm', '.h'))):
431 continue
432 for lnum, line in f.ChangedContents():
433 if input_api.re.search(pattern, line):
dchenge07de812016-06-20 19:27:17434 errors.append(output_api.PresubmitError(
435 ('%s:%d: Use of DCHECK_IS_ON() must be written as "#if ' +
436 'DCHECK_IS_ON()", not forgetting the braces.')
437 % (f.LocalPath(), lnum)))
danakj61c1aa22015-10-26 19:55:52438 return errors
439
440
mcasasb7440c282015-02-04 14:52:19441def _FindHistogramNameInLine(histogram_name, line):
442 """Tries to find a histogram name or prefix in a line."""
443 if not "affected-histogram" in line:
444 return histogram_name in line
445 # A histogram_suffixes tag type has an affected-histogram name as a prefix of
446 # the histogram_name.
447 if not '"' in line:
448 return False
449 histogram_prefix = line.split('\"')[1]
450 return histogram_prefix in histogram_name
451
452
453def _CheckUmaHistogramChanges(input_api, output_api):
454 """Check that UMA histogram names in touched lines can still be found in other
455 lines of the patch or in histograms.xml. Note that this check would not catch
456 the reverse: changes in histograms.xml not matched in the code itself."""
457 touched_histograms = []
458 histograms_xml_modifications = []
459 pattern = input_api.re.compile('UMA_HISTOGRAM.*\("(.*)"')
460 for f in input_api.AffectedFiles():
461 # If histograms.xml itself is modified, keep the modified lines for later.
462 if f.LocalPath().endswith(('histograms.xml')):
463 histograms_xml_modifications = f.ChangedContents()
464 continue
465 if not f.LocalPath().endswith(('cc', 'mm', 'cpp')):
466 continue
467 for line_num, line in f.ChangedContents():
468 found = pattern.search(line)
469 if found:
470 touched_histograms.append([found.group(1), f, line_num])
471
472 # Search for the touched histogram names in the local modifications to
473 # histograms.xml, and, if not found, on the base histograms.xml file.
474 unmatched_histograms = []
475 for histogram_info in touched_histograms:
476 histogram_name_found = False
477 for line_num, line in histograms_xml_modifications:
478 histogram_name_found = _FindHistogramNameInLine(histogram_info[0], line)
479 if histogram_name_found:
480 break
481 if not histogram_name_found:
482 unmatched_histograms.append(histogram_info)
483
eromanb90c82e7e32015-04-01 15:13:49484 histograms_xml_path = 'tools/metrics/histograms/histograms.xml'
mcasasb7440c282015-02-04 14:52:19485 problems = []
486 if unmatched_histograms:
eromanb90c82e7e32015-04-01 15:13:49487 with open(histograms_xml_path) as histograms_xml:
mcasasb7440c282015-02-04 14:52:19488 for histogram_name, f, line_num in unmatched_histograms:
mcasas39c1b8b2015-02-25 15:33:45489 histograms_xml.seek(0)
mcasasb7440c282015-02-04 14:52:19490 histogram_name_found = False
491 for line in histograms_xml:
492 histogram_name_found = _FindHistogramNameInLine(histogram_name, line)
493 if histogram_name_found:
494 break
495 if not histogram_name_found:
496 problems.append(' [%s:%d] %s' %
497 (f.LocalPath(), line_num, histogram_name))
498
499 if not problems:
500 return []
501 return [output_api.PresubmitPromptWarning('Some UMA_HISTOGRAM lines have '
502 'been modified and the associated histogram name has no match in either '
eromanb90c82e7e32015-04-01 15:13:49503 '%s or the modifications of it:' % (histograms_xml_path), problems)]
mcasasb7440c282015-02-04 14:52:19504
wnwenbdc444e2016-05-25 13:44:15505
yolandyandaabc6d2016-04-18 18:29:39506def _CheckFlakyTestUsage(input_api, output_api):
507 """Check that FlakyTest annotation is our own instead of the android one"""
508 pattern = input_api.re.compile(r'import android.test.FlakyTest;')
509 files = []
510 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
511 if f.LocalPath().endswith('Test.java'):
512 if pattern.search(input_api.ReadFile(f)):
513 files.append(f)
514 if len(files):
515 return [output_api.PresubmitError(
516 'Use org.chromium.base.test.util.FlakyTest instead of '
517 'android.test.FlakyTest',
518 files)]
519 return []
mcasasb7440c282015-02-04 14:52:19520
wnwenbdc444e2016-05-25 13:44:15521
[email protected]8ea5d4b2011-09-13 21:49:22522def _CheckNoNewWStrings(input_api, output_api):
523 """Checks to make sure we don't introduce use of wstrings."""
[email protected]55463aa62011-10-12 00:48:27524 problems = []
[email protected]8ea5d4b2011-09-13 21:49:22525 for f in input_api.AffectedFiles():
[email protected]b5c24292011-11-28 14:38:20526 if (not f.LocalPath().endswith(('.cc', '.h')) or
scottmge6f04402014-11-05 01:59:57527 f.LocalPath().endswith(('test.cc', '_win.cc', '_win.h')) or
528 '/win/' in f.LocalPath()):
[email protected]b5c24292011-11-28 14:38:20529 continue
[email protected]8ea5d4b2011-09-13 21:49:22530
[email protected]a11dbe9b2012-08-07 01:32:58531 allowWString = False
[email protected]b5c24292011-11-28 14:38:20532 for line_num, line in f.ChangedContents():
[email protected]a11dbe9b2012-08-07 01:32:58533 if 'presubmit: allow wstring' in line:
534 allowWString = True
535 elif not allowWString and 'wstring' in line:
[email protected]55463aa62011-10-12 00:48:27536 problems.append(' %s:%d' % (f.LocalPath(), line_num))
[email protected]a11dbe9b2012-08-07 01:32:58537 allowWString = False
538 else:
539 allowWString = False
[email protected]8ea5d4b2011-09-13 21:49:22540
[email protected]55463aa62011-10-12 00:48:27541 if not problems:
542 return []
543 return [output_api.PresubmitPromptWarning('New code should not use wstrings.'
[email protected]a11dbe9b2012-08-07 01:32:58544 ' If you are calling a cross-platform API that accepts a wstring, '
545 'fix the API.\n' +
[email protected]55463aa62011-10-12 00:48:27546 '\n'.join(problems))]
[email protected]8ea5d4b2011-09-13 21:49:22547
548
[email protected]2a8ac9c2011-10-19 17:20:44549def _CheckNoDEPSGIT(input_api, output_api):
550 """Make sure .DEPS.git is never modified manually."""
551 if any(f.LocalPath().endswith('.DEPS.git') for f in
552 input_api.AffectedFiles()):
553 return [output_api.PresubmitError(
554 'Never commit changes to .DEPS.git. This file is maintained by an\n'
555 'automated system based on what\'s in DEPS and your changes will be\n'
556 'overwritten.\n'
[email protected]cb706912014-06-28 20:46:34557 '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:44558 'for more information')]
559 return []
560
561
tandriief664692014-09-23 14:51:47562def _CheckValidHostsInDEPS(input_api, output_api):
563 """Checks that DEPS file deps are from allowed_hosts."""
564 # Run only if DEPS file has been modified to annoy fewer bystanders.
565 if all(f.LocalPath() != 'DEPS' for f in input_api.AffectedFiles()):
566 return []
567 # Outsource work to gclient verify
568 try:
569 input_api.subprocess.check_output(['gclient', 'verify'])
570 return []
571 except input_api.subprocess.CalledProcessError, error:
572 return [output_api.PresubmitError(
573 'DEPS file must have only git dependencies.',
574 long_text=error.output)]
575
576
[email protected]127f18ec2012-06-16 05:05:59577def _CheckNoBannedFunctions(input_api, output_api):
578 """Make sure that banned functions are not used."""
579 warnings = []
580 errors = []
581
wnwenbdc444e2016-05-25 13:44:15582 def IsBlacklisted(affected_file, blacklist):
583 local_path = affected_file.LocalPath()
584 for item in blacklist:
585 if input_api.re.match(item, local_path):
586 return True
587 return False
588
589 def CheckForMatch(affected_file, line_num, line, func_name, message, error):
590 matched = False
591 if func_name[0:1] == '/':
592 regex = func_name[1:]
593 if input_api.re.search(regex, line):
594 matched = True
595 elif func_name in line:
dchenge07de812016-06-20 19:27:17596 matched = True
wnwenbdc444e2016-05-25 13:44:15597 if matched:
dchenge07de812016-06-20 19:27:17598 problems = warnings
wnwenbdc444e2016-05-25 13:44:15599 if error:
dchenge07de812016-06-20 19:27:17600 problems = errors
wnwenbdc444e2016-05-25 13:44:15601 problems.append(' %s:%d:' % (affected_file.LocalPath(), line_num))
602 for message_line in message:
603 problems.append(' %s' % message_line)
604
[email protected]127f18ec2012-06-16 05:05:59605 file_filter = lambda f: f.LocalPath().endswith(('.mm', '.m', '.h'))
606 for f in input_api.AffectedFiles(file_filter=file_filter):
607 for line_num, line in f.ChangedContents():
608 for func_name, message, error in _BANNED_OBJC_FUNCTIONS:
wnwenbdc444e2016-05-25 13:44:15609 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:59610
611 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
612 for f in input_api.AffectedFiles(file_filter=file_filter):
613 for line_num, line in f.ChangedContents():
[email protected]7345da02012-11-27 14:31:49614 for func_name, message, error, excluded_paths in _BANNED_CPP_FUNCTIONS:
[email protected]7345da02012-11-27 14:31:49615 if IsBlacklisted(f, excluded_paths):
616 continue
wnwenbdc444e2016-05-25 13:44:15617 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:59618
619 result = []
620 if (warnings):
621 result.append(output_api.PresubmitPromptWarning(
622 'Banned functions were used.\n' + '\n'.join(warnings)))
623 if (errors):
624 result.append(output_api.PresubmitError(
625 'Banned functions were used.\n' + '\n'.join(errors)))
626 return result
627
628
[email protected]6c063c62012-07-11 19:11:06629def _CheckNoPragmaOnce(input_api, output_api):
630 """Make sure that banned functions are not used."""
631 files = []
632 pattern = input_api.re.compile(r'^#pragma\s+once',
633 input_api.re.MULTILINE)
634 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
635 if not f.LocalPath().endswith('.h'):
636 continue
637 contents = input_api.ReadFile(f)
638 if pattern.search(contents):
639 files.append(f)
640
641 if files:
642 return [output_api.PresubmitError(
643 'Do not use #pragma once in header files.\n'
644 'See http://www.chromium.org/developers/coding-style#TOC-File-headers',
645 files)]
646 return []
647
[email protected]127f18ec2012-06-16 05:05:59648
[email protected]e7479052012-09-19 00:26:12649def _CheckNoTrinaryTrueFalse(input_api, output_api):
650 """Checks to make sure we don't introduce use of foo ? true : false."""
651 problems = []
652 pattern = input_api.re.compile(r'\?\s*(true|false)\s*:\s*(true|false)')
653 for f in input_api.AffectedFiles():
654 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
655 continue
656
657 for line_num, line in f.ChangedContents():
658 if pattern.match(line):
659 problems.append(' %s:%d' % (f.LocalPath(), line_num))
660
661 if not problems:
662 return []
663 return [output_api.PresubmitPromptWarning(
664 'Please consider avoiding the "? true : false" pattern if possible.\n' +
665 '\n'.join(problems))]
666
667
[email protected]55f9f382012-07-31 11:02:18668def _CheckUnwantedDependencies(input_api, output_api):
669 """Runs checkdeps on #include statements added in this
670 change. Breaking - rules is an error, breaking ! rules is a
671 warning.
672 """
mohan.reddyf21db962014-10-16 12:26:47673 import sys
[email protected]55f9f382012-07-31 11:02:18674 # We need to wait until we have an input_api object and use this
675 # roundabout construct to import checkdeps because this file is
676 # eval-ed and thus doesn't have __file__.
677 original_sys_path = sys.path
678 try:
679 sys.path = sys.path + [input_api.os_path.join(
[email protected]5298cc982014-05-29 20:53:47680 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
[email protected]55f9f382012-07-31 11:02:18681 import checkdeps
682 from cpp_checker import CppChecker
683 from rules import Rule
684 finally:
685 # Restore sys.path to what it was before.
686 sys.path = original_sys_path
687
688 added_includes = []
689 for f in input_api.AffectedFiles():
690 if not CppChecker.IsCppFile(f.LocalPath()):
691 continue
692
693 changed_lines = [line for line_num, line in f.ChangedContents()]
694 added_includes.append([f.LocalPath(), changed_lines])
695
[email protected]26385172013-05-09 23:11:35696 deps_checker = checkdeps.DepsChecker(input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:18697
698 error_descriptions = []
699 warning_descriptions = []
700 for path, rule_type, rule_description in deps_checker.CheckAddedCppIncludes(
701 added_includes):
702 description_with_path = '%s\n %s' % (path, rule_description)
703 if rule_type == Rule.DISALLOW:
704 error_descriptions.append(description_with_path)
705 else:
706 warning_descriptions.append(description_with_path)
707
708 results = []
709 if error_descriptions:
710 results.append(output_api.PresubmitError(
711 'You added one or more #includes that violate checkdeps rules.',
712 error_descriptions))
713 if warning_descriptions:
[email protected]f7051d52013-04-02 18:31:42714 results.append(output_api.PresubmitPromptOrNotify(
[email protected]55f9f382012-07-31 11:02:18715 'You added one or more #includes of files that are temporarily\n'
716 'allowed but being removed. Can you avoid introducing the\n'
717 '#include? See relevant DEPS file(s) for details and contacts.',
718 warning_descriptions))
719 return results
720
721
[email protected]fbcafe5a2012-08-08 15:31:22722def _CheckFilePermissions(input_api, output_api):
723 """Check that all files have their permissions properly set."""
[email protected]791507202014-02-03 23:19:15724 if input_api.platform == 'win32':
725 return []
raphael.kubo.da.costac1d13e60b2016-04-01 11:49:29726 checkperms_tool = input_api.os_path.join(
727 input_api.PresubmitLocalPath(),
728 'tools', 'checkperms', 'checkperms.py')
729 args = [input_api.python_executable, checkperms_tool,
mohan.reddyf21db962014-10-16 12:26:47730 '--root', input_api.change.RepositoryRoot()]
[email protected]fbcafe5a2012-08-08 15:31:22731 for f in input_api.AffectedFiles():
732 args += ['--file', f.LocalPath()]
phajdan.jr5ea54792015-10-14 10:51:11733 try:
734 input_api.subprocess.check_output(args)
735 return []
736 except input_api.subprocess.CalledProcessError as error:
737 return [output_api.PresubmitError(
738 'checkperms.py failed:',
739 long_text=error.output)]
[email protected]fbcafe5a2012-08-08 15:31:22740
741
[email protected]c8278b32012-10-30 20:35:49742def _CheckNoAuraWindowPropertyHInHeaders(input_api, output_api):
743 """Makes sure we don't include ui/aura/window_property.h
744 in header files.
745 """
746 pattern = input_api.re.compile(r'^#include\s*"ui/aura/window_property.h"')
747 errors = []
748 for f in input_api.AffectedFiles():
749 if not f.LocalPath().endswith('.h'):
750 continue
751 for line_num, line in f.ChangedContents():
752 if pattern.match(line):
753 errors.append(' %s:%d' % (f.LocalPath(), line_num))
754
755 results = []
756 if errors:
757 results.append(output_api.PresubmitError(
758 'Header files should not include ui/aura/window_property.h', errors))
759 return results
760
761
[email protected]cf9b78f2012-11-14 11:40:28762def _CheckIncludeOrderForScope(scope, input_api, file_path, changed_linenums):
763 """Checks that the lines in scope occur in the right order.
764
765 1. C system files in alphabetical order
766 2. C++ system files in alphabetical order
767 3. Project's .h files
768 """
769
770 c_system_include_pattern = input_api.re.compile(r'\s*#include <.*\.h>')
771 cpp_system_include_pattern = input_api.re.compile(r'\s*#include <.*>')
772 custom_include_pattern = input_api.re.compile(r'\s*#include ".*')
773
774 C_SYSTEM_INCLUDES, CPP_SYSTEM_INCLUDES, CUSTOM_INCLUDES = range(3)
775
776 state = C_SYSTEM_INCLUDES
777
778 previous_line = ''
[email protected]728b9bb2012-11-14 20:38:57779 previous_line_num = 0
[email protected]cf9b78f2012-11-14 11:40:28780 problem_linenums = []
brucedawson70fadb02015-06-30 17:47:55781 out_of_order = " - line belongs before previous line"
[email protected]cf9b78f2012-11-14 11:40:28782 for line_num, line in scope:
783 if c_system_include_pattern.match(line):
784 if state != C_SYSTEM_INCLUDES:
brucedawson70fadb02015-06-30 17:47:55785 problem_linenums.append((line_num, previous_line_num,
786 " - C system include file in wrong block"))
[email protected]cf9b78f2012-11-14 11:40:28787 elif previous_line and previous_line > line:
brucedawson70fadb02015-06-30 17:47:55788 problem_linenums.append((line_num, previous_line_num,
789 out_of_order))
[email protected]cf9b78f2012-11-14 11:40:28790 elif cpp_system_include_pattern.match(line):
791 if state == C_SYSTEM_INCLUDES:
792 state = CPP_SYSTEM_INCLUDES
793 elif state == CUSTOM_INCLUDES:
brucedawson70fadb02015-06-30 17:47:55794 problem_linenums.append((line_num, previous_line_num,
795 " - c++ system include file in wrong block"))
[email protected]cf9b78f2012-11-14 11:40:28796 elif previous_line and previous_line > line:
brucedawson70fadb02015-06-30 17:47:55797 problem_linenums.append((line_num, previous_line_num, out_of_order))
[email protected]cf9b78f2012-11-14 11:40:28798 elif custom_include_pattern.match(line):
799 if state != CUSTOM_INCLUDES:
800 state = CUSTOM_INCLUDES
801 elif previous_line and previous_line > line:
brucedawson70fadb02015-06-30 17:47:55802 problem_linenums.append((line_num, previous_line_num, out_of_order))
[email protected]cf9b78f2012-11-14 11:40:28803 else:
brucedawson70fadb02015-06-30 17:47:55804 problem_linenums.append((line_num, previous_line_num,
805 "Unknown include type"))
[email protected]cf9b78f2012-11-14 11:40:28806 previous_line = line
[email protected]728b9bb2012-11-14 20:38:57807 previous_line_num = line_num
[email protected]cf9b78f2012-11-14 11:40:28808
809 warnings = []
brucedawson70fadb02015-06-30 17:47:55810 for (line_num, previous_line_num, failure_type) in problem_linenums:
[email protected]728b9bb2012-11-14 20:38:57811 if line_num in changed_linenums or previous_line_num in changed_linenums:
brucedawson70fadb02015-06-30 17:47:55812 warnings.append(' %s:%d:%s' % (file_path, line_num, failure_type))
[email protected]cf9b78f2012-11-14 11:40:28813 return warnings
814
815
[email protected]ac294a12012-12-06 16:38:43816def _CheckIncludeOrderInFile(input_api, f, changed_linenums):
[email protected]cf9b78f2012-11-14 11:40:28817 """Checks the #include order for the given file f."""
818
[email protected]2299dcf2012-11-15 19:56:24819 system_include_pattern = input_api.re.compile(r'\s*#include \<.*')
[email protected]23093b62013-09-20 12:16:30820 # Exclude the following includes from the check:
821 # 1) #include <.../...>, e.g., <sys/...> includes often need to appear in a
822 # specific order.
823 # 2) <atlbase.h>, "build/build_config.h"
824 excluded_include_pattern = input_api.re.compile(
825 r'\s*#include (\<.*/.*|\<atlbase\.h\>|"build/build_config.h")')
[email protected]2299dcf2012-11-15 19:56:24826 custom_include_pattern = input_api.re.compile(r'\s*#include "(?P<FILE>.*)"')
[email protected]3e83618c2013-10-09 22:32:33827 # Match the final or penultimate token if it is xxxtest so we can ignore it
828 # when considering the special first include.
829 test_file_tag_pattern = input_api.re.compile(
830 r'_[a-z]+test(?=(_[a-zA-Z0-9]+)?\.)')
[email protected]0e5c1852012-12-18 20:17:11831 if_pattern = input_api.re.compile(
832 r'\s*#\s*(if|elif|else|endif|define|undef).*')
833 # Some files need specialized order of includes; exclude such files from this
834 # check.
835 uncheckable_includes_pattern = input_api.re.compile(
836 r'\s*#include '
837 '("ipc/.*macros\.h"|<windows\.h>|".*gl.*autogen.h")\s*')
[email protected]cf9b78f2012-11-14 11:40:28838
839 contents = f.NewContents()
840 warnings = []
841 line_num = 0
842
[email protected]ac294a12012-12-06 16:38:43843 # Handle the special first include. If the first include file is
844 # some/path/file.h, the corresponding including file can be some/path/file.cc,
845 # some/other/path/file.cc, some/path/file_platform.cc, some/path/file-suffix.h
846 # etc. It's also possible that no special first include exists.
[email protected]3e83618c2013-10-09 22:32:33847 # If the included file is some/path/file_platform.h the including file could
848 # also be some/path/file_xxxtest_platform.h.
849 including_file_base_name = test_file_tag_pattern.sub(
850 '', input_api.os_path.basename(f.LocalPath()))
851
[email protected]ac294a12012-12-06 16:38:43852 for line in contents:
853 line_num += 1
854 if system_include_pattern.match(line):
855 # No special first include -> process the line again along with normal
856 # includes.
857 line_num -= 1
858 break
859 match = custom_include_pattern.match(line)
860 if match:
861 match_dict = match.groupdict()
[email protected]3e83618c2013-10-09 22:32:33862 header_basename = test_file_tag_pattern.sub(
863 '', input_api.os_path.basename(match_dict['FILE'])).replace('.h', '')
864
865 if header_basename not in including_file_base_name:
[email protected]2299dcf2012-11-15 19:56:24866 # No special first include -> process the line again along with normal
867 # includes.
868 line_num -= 1
[email protected]ac294a12012-12-06 16:38:43869 break
[email protected]cf9b78f2012-11-14 11:40:28870
871 # Split into scopes: Each region between #if and #endif is its own scope.
872 scopes = []
873 current_scope = []
874 for line in contents[line_num:]:
875 line_num += 1
[email protected]0e5c1852012-12-18 20:17:11876 if uncheckable_includes_pattern.match(line):
[email protected]4436c9e2014-01-07 23:19:54877 continue
[email protected]2309b0fa02012-11-16 12:18:27878 if if_pattern.match(line):
[email protected]cf9b78f2012-11-14 11:40:28879 scopes.append(current_scope)
880 current_scope = []
[email protected]962f117e2012-11-22 18:11:56881 elif ((system_include_pattern.match(line) or
882 custom_include_pattern.match(line)) and
883 not excluded_include_pattern.match(line)):
[email protected]cf9b78f2012-11-14 11:40:28884 current_scope.append((line_num, line))
885 scopes.append(current_scope)
886
887 for scope in scopes:
888 warnings.extend(_CheckIncludeOrderForScope(scope, input_api, f.LocalPath(),
889 changed_linenums))
890 return warnings
891
892
893def _CheckIncludeOrder(input_api, output_api):
894 """Checks that the #include order is correct.
895
896 1. The corresponding header for source files.
897 2. C system files in alphabetical order
898 3. C++ system files in alphabetical order
899 4. Project's .h files in alphabetical order
900
[email protected]ac294a12012-12-06 16:38:43901 Each region separated by #if, #elif, #else, #endif, #define and #undef follows
902 these rules separately.
[email protected]cf9b78f2012-11-14 11:40:28903 """
[email protected]e120b012014-08-15 19:08:35904 def FileFilterIncludeOrder(affected_file):
905 black_list = (_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
906 return input_api.FilterSourceFile(affected_file, black_list=black_list)
[email protected]cf9b78f2012-11-14 11:40:28907
908 warnings = []
[email protected]e120b012014-08-15 19:08:35909 for f in input_api.AffectedFiles(file_filter=FileFilterIncludeOrder):
tapted574f09c2015-05-19 13:08:08910 if f.LocalPath().endswith(('.cc', '.h', '.mm')):
[email protected]ac294a12012-12-06 16:38:43911 changed_linenums = set(line_num for line_num, _ in f.ChangedContents())
912 warnings.extend(_CheckIncludeOrderInFile(input_api, f, changed_linenums))
[email protected]cf9b78f2012-11-14 11:40:28913
914 results = []
915 if warnings:
[email protected]f7051d52013-04-02 18:31:42916 results.append(output_api.PresubmitPromptOrNotify(_INCLUDE_ORDER_WARNING,
[email protected]120cf540d2012-12-10 17:55:53917 warnings))
[email protected]cf9b78f2012-11-14 11:40:28918 return results
919
920
[email protected]70ca77752012-11-20 03:45:03921def _CheckForVersionControlConflictsInFile(input_api, f):
922 pattern = input_api.re.compile('^(?:<<<<<<<|>>>>>>>) |^=======$')
923 errors = []
924 for line_num, line in f.ChangedContents():
dbeam95c35a2f2015-06-02 01:40:23925 if f.LocalPath().endswith('.md'):
926 # First-level headers in markdown look a lot like version control
927 # conflict markers. http://daringfireball.net/projects/markdown/basics
928 continue
[email protected]70ca77752012-11-20 03:45:03929 if pattern.match(line):
930 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
931 return errors
932
933
934def _CheckForVersionControlConflicts(input_api, output_api):
935 """Usually this is not intentional and will cause a compile failure."""
936 errors = []
937 for f in input_api.AffectedFiles():
938 errors.extend(_CheckForVersionControlConflictsInFile(input_api, f))
939
940 results = []
941 if errors:
942 results.append(output_api.PresubmitError(
943 'Version control conflict markers found, please resolve.', errors))
944 return results
945
946
[email protected]06e6d0ff2012-12-11 01:36:44947def _CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api):
948 def FilterFile(affected_file):
949 """Filter function for use with input_api.AffectedSourceFiles,
950 below. This filters out everything except non-test files from
951 top-level directories that generally speaking should not hard-code
952 service URLs (e.g. src/android_webview/, src/content/ and others).
953 """
954 return input_api.FilterSourceFile(
955 affected_file,
[email protected]78bb39d62012-12-11 15:11:56956 white_list=(r'^(android_webview|base|content|net)[\\\/].*', ),
[email protected]06e6d0ff2012-12-11 01:36:44957 black_list=(_EXCLUDED_PATHS +
958 _TEST_CODE_EXCLUDED_PATHS +
959 input_api.DEFAULT_BLACK_LIST))
960
reillyi38965732015-11-16 18:27:33961 base_pattern = ('"[^"]*(google|googleapis|googlezip|googledrive|appspot)'
962 '\.(com|net)[^"]*"')
[email protected]de4f7d22013-05-23 14:27:46963 comment_pattern = input_api.re.compile('//.*%s' % base_pattern)
964 pattern = input_api.re.compile(base_pattern)
[email protected]06e6d0ff2012-12-11 01:36:44965 problems = [] # items are (filename, line_number, line)
966 for f in input_api.AffectedSourceFiles(FilterFile):
967 for line_num, line in f.ChangedContents():
[email protected]de4f7d22013-05-23 14:27:46968 if not comment_pattern.search(line) and pattern.search(line):
[email protected]06e6d0ff2012-12-11 01:36:44969 problems.append((f.LocalPath(), line_num, line))
970
971 if problems:
[email protected]f7051d52013-04-02 18:31:42972 return [output_api.PresubmitPromptOrNotify(
[email protected]06e6d0ff2012-12-11 01:36:44973 'Most layers below src/chrome/ should not hardcode service URLs.\n'
[email protected]b0149772014-03-27 16:47:58974 'Are you sure this is correct?',
[email protected]06e6d0ff2012-12-11 01:36:44975 [' %s:%d: %s' % (
976 problem[0], problem[1], problem[2]) for problem in problems])]
[email protected]2fdd1f362013-01-16 03:56:03977 else:
978 return []
[email protected]06e6d0ff2012-12-11 01:36:44979
980
[email protected]d2530012013-01-25 16:39:27981def _CheckNoAbbreviationInPngFileName(input_api, output_api):
982 """Makes sure there are no abbreviations in the name of PNG files.
binji0dcdf342014-12-12 18:32:31983 The native_client_sdk directory is excluded because it has auto-generated PNG
984 files for documentation.
[email protected]d2530012013-01-25 16:39:27985 """
[email protected]d2530012013-01-25 16:39:27986 errors = []
binji0dcdf342014-12-12 18:32:31987 white_list = (r'.*_[a-z]_.*\.png$|.*_[a-z]\.png$',)
988 black_list = (r'^native_client_sdk[\\\/]',)
989 file_filter = lambda f: input_api.FilterSourceFile(
990 f, white_list=white_list, black_list=black_list)
991 for f in input_api.AffectedFiles(include_deletes=False,
992 file_filter=file_filter):
993 errors.append(' %s' % f.LocalPath())
[email protected]d2530012013-01-25 16:39:27994
995 results = []
996 if errors:
997 results.append(output_api.PresubmitError(
998 'The name of PNG files should not have abbreviations. \n'
999 'Use _hover.png, _center.png, instead of _h.png, _c.png.\n'
1000 'Contact [email protected] if you have questions.', errors))
1001 return results
1002
1003
[email protected]14a6131c2014-01-08 01:15:411004def _FilesToCheckForIncomingDeps(re, changed_lines):
[email protected]f32e2d1e2013-07-26 21:39:081005 """Helper method for _CheckAddedDepsHaveTargetApprovals. Returns
[email protected]14a6131c2014-01-08 01:15:411006 a set of DEPS entries that we should look up.
1007
1008 For a directory (rather than a specific filename) we fake a path to
1009 a specific filename by adding /DEPS. This is chosen as a file that
1010 will seldom or never be subject to per-file include_rules.
1011 """
[email protected]2b438d62013-11-14 17:54:141012 # We ignore deps entries on auto-generated directories.
1013 AUTO_GENERATED_DIRS = ['grit', 'jni']
[email protected]f32e2d1e2013-07-26 21:39:081014
1015 # This pattern grabs the path without basename in the first
1016 # parentheses, and the basename (if present) in the second. It
1017 # relies on the simple heuristic that if there is a basename it will
1018 # be a header file ending in ".h".
1019 pattern = re.compile(
1020 r"""['"]\+([^'"]+?)(/[a-zA-Z0-9_]+\.h)?['"].*""")
[email protected]2b438d62013-11-14 17:54:141021 results = set()
[email protected]f32e2d1e2013-07-26 21:39:081022 for changed_line in changed_lines:
1023 m = pattern.match(changed_line)
1024 if m:
1025 path = m.group(1)
[email protected]2b438d62013-11-14 17:54:141026 if path.split('/')[0] not in AUTO_GENERATED_DIRS:
[email protected]14a6131c2014-01-08 01:15:411027 if m.group(2):
1028 results.add('%s%s' % (path, m.group(2)))
1029 else:
1030 results.add('%s/DEPS' % path)
[email protected]f32e2d1e2013-07-26 21:39:081031 return results
1032
1033
[email protected]e871964c2013-05-13 14:14:551034def _CheckAddedDepsHaveTargetApprovals(input_api, output_api):
1035 """When a dependency prefixed with + is added to a DEPS file, we
1036 want to make sure that the change is reviewed by an OWNER of the
1037 target file or directory, to avoid layering violations from being
1038 introduced. This check verifies that this happens.
1039 """
1040 changed_lines = set()
jochen53efcdd2016-01-29 05:09:241041
1042 file_filter = lambda f: not input_api.re.match(
1043 r"^third_party[\\\/]WebKit[\\\/].*", f.LocalPath())
1044 for f in input_api.AffectedFiles(include_deletes=False,
1045 file_filter=file_filter):
[email protected]e871964c2013-05-13 14:14:551046 filename = input_api.os_path.basename(f.LocalPath())
1047 if filename == 'DEPS':
1048 changed_lines |= set(line.strip()
1049 for line_num, line
1050 in f.ChangedContents())
1051 if not changed_lines:
1052 return []
1053
[email protected]14a6131c2014-01-08 01:15:411054 virtual_depended_on_files = _FilesToCheckForIncomingDeps(input_api.re,
1055 changed_lines)
[email protected]e871964c2013-05-13 14:14:551056 if not virtual_depended_on_files:
1057 return []
1058
1059 if input_api.is_committing:
1060 if input_api.tbr:
1061 return [output_api.PresubmitNotifyResult(
1062 '--tbr was specified, skipping OWNERS check for DEPS additions')]
Paweł Hajdan, Jrbe6739ea2016-04-28 15:07:271063 if input_api.dry_run:
1064 return [output_api.PresubmitNotifyResult(
1065 'This is a dry run, skipping OWNERS check for DEPS additions')]
[email protected]e871964c2013-05-13 14:14:551066 if not input_api.change.issue:
1067 return [output_api.PresubmitError(
1068 "DEPS approval by OWNERS check failed: this change has "
1069 "no Rietveld issue number, so we can't check it for approvals.")]
1070 output = output_api.PresubmitError
1071 else:
1072 output = output_api.PresubmitNotifyResult
1073
1074 owners_db = input_api.owners_db
tandriied3b7e12016-05-12 14:38:501075 owner_email, reviewers = (
1076 input_api.canned_checks.GetCodereviewOwnerAndReviewers(
1077 input_api,
1078 owners_db.email_regexp,
1079 approval_needed=input_api.is_committing))
[email protected]e871964c2013-05-13 14:14:551080
1081 owner_email = owner_email or input_api.change.author_email
1082
[email protected]de4f7d22013-05-23 14:27:461083 reviewers_plus_owner = set(reviewers)
[email protected]e71c6082013-05-22 02:28:511084 if owner_email:
[email protected]de4f7d22013-05-23 14:27:461085 reviewers_plus_owner.add(owner_email)
[email protected]e871964c2013-05-13 14:14:551086 missing_files = owners_db.files_not_covered_by(virtual_depended_on_files,
1087 reviewers_plus_owner)
[email protected]14a6131c2014-01-08 01:15:411088
1089 # We strip the /DEPS part that was added by
1090 # _FilesToCheckForIncomingDeps to fake a path to a file in a
1091 # directory.
1092 def StripDeps(path):
1093 start_deps = path.rfind('/DEPS')
1094 if start_deps != -1:
1095 return path[:start_deps]
1096 else:
1097 return path
1098 unapproved_dependencies = ["'+%s'," % StripDeps(path)
[email protected]e871964c2013-05-13 14:14:551099 for path in missing_files]
1100
1101 if unapproved_dependencies:
1102 output_list = [
Paweł Hajdan, Jrec17f882016-07-04 14:16:151103 output('You need LGTM from owners of depends-on paths in DEPS that were '
1104 'modified in this CL:\n %s' %
1105 '\n '.join(sorted(unapproved_dependencies)))]
1106 suggested_owners = owners_db.reviewers_for(missing_files, owner_email)
1107 output_list.append(output(
1108 'Suggested missing target path OWNERS:\n %s' %
1109 '\n '.join(suggested_owners or [])))
[email protected]e871964c2013-05-13 14:14:551110 return output_list
1111
1112 return []
1113
1114
[email protected]85218562013-11-22 07:41:401115def _CheckSpamLogging(input_api, output_api):
1116 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
1117 black_list = (_EXCLUDED_PATHS +
1118 _TEST_CODE_EXCLUDED_PATHS +
1119 input_api.DEFAULT_BLACK_LIST +
[email protected]6f742dd02013-11-26 23:19:501120 (r"^base[\\\/]logging\.h$",
[email protected]80f360a2014-01-23 01:36:191121 r"^base[\\\/]logging\.cc$",
[email protected]8dc338c2013-12-09 16:28:481122 r"^chrome[\\\/]app[\\\/]chrome_main_delegate\.cc$",
[email protected]6e268db2013-12-04 01:41:461123 r"^chrome[\\\/]browser[\\\/]chrome_browser_main\.cc$",
[email protected]4de75262013-12-18 23:16:121124 r"^chrome[\\\/]browser[\\\/]ui[\\\/]startup[\\\/]"
1125 r"startup_browser_creator\.cc$",
[email protected]fe0e6e12013-12-04 05:52:581126 r"^chrome[\\\/]installer[\\\/]setup[\\\/].*",
[email protected]8cf6f842014-08-08 21:33:161127 r"chrome[\\\/]browser[\\\/]diagnostics[\\\/]" +
[email protected]f5b9a3f342014-08-08 22:06:031128 r"diagnostics_writer\.cc$",
[email protected]9f13b602014-08-07 02:59:151129 r"^chrome_elf[\\\/]dll_hash[\\\/]dll_hash_main\.cc$",
1130 r"^chromecast[\\\/]",
1131 r"^cloud_print[\\\/]",
jochen34415e52015-07-10 08:34:311132 r"^components[\\\/]html_viewer[\\\/]"
1133 r"web_test_delegate_impl\.cc$",
peter80739bb2015-10-20 11:17:461134 # TODO(peter): Remove this exception. https://crbug.com/534537
1135 r"^content[\\\/]browser[\\\/]notifications[\\\/]"
1136 r"notification_event_dispatcher_impl\.cc$",
[email protected]9056e732014-01-08 06:25:251137 r"^content[\\\/]common[\\\/]gpu[\\\/]client[\\\/]"
1138 r"gl_helper_benchmark\.cc$",
altimin979ea2e12016-05-18 16:16:241139 r"^courgette[\\\/]courgette_minimal_tool\.cc$",
thestigc9e38a22014-09-13 01:02:111140 r"^courgette[\\\/]courgette_tool\.cc$",
[email protected]9f13b602014-08-07 02:59:151141 r"^extensions[\\\/]renderer[\\\/]logging_native_handler\.cc$",
prashant.nb0252f62014-11-08 05:02:111142 r"^ipc[\\\/]ipc_logging\.cc$",
[email protected]9c36d922014-03-24 16:47:521143 r"^native_client_sdk[\\\/]",
[email protected]cdbdced2013-11-27 21:35:501144 r"^remoting[\\\/]base[\\\/]logging\.h$",
[email protected]67c96ab2013-12-17 02:05:361145 r"^remoting[\\\/]host[\\\/].*",
[email protected]8232f8fd2013-12-14 00:52:311146 r"^sandbox[\\\/]linux[\\\/].*",
[email protected]0b7a21e2014-02-11 18:38:131147 r"^tools[\\\/]",
thestig22dfc4012014-09-05 08:29:441148 r"^ui[\\\/]aura[\\\/]bench[\\\/]bench_main\.cc$",
halliwellf7fc61c62016-01-28 17:18:451149 r"^ui[\\\/]ozone[\\\/]platform[\\\/]cast[\\\/]",
vchigrin14251492015-01-12 08:09:021150 r"^storage[\\\/]browser[\\\/]fileapi[\\\/]" +
thestig22dfc4012014-09-05 08:29:441151 r"dump_file_system.cc$",))
[email protected]85218562013-11-22 07:41:401152 source_file_filter = lambda x: input_api.FilterSourceFile(
1153 x, white_list=(file_inclusion_pattern,), black_list=black_list)
1154
1155 log_info = []
1156 printf = []
1157
1158 for f in input_api.AffectedSourceFiles(source_file_filter):
1159 contents = input_api.ReadFile(f, 'rb')
mohan.reddyf21db962014-10-16 12:26:471160 if input_api.re.search(r"\bD?LOG\s*\(\s*INFO\s*\)", contents):
[email protected]85218562013-11-22 07:41:401161 log_info.append(f.LocalPath())
mohan.reddyf21db962014-10-16 12:26:471162 elif input_api.re.search(r"\bD?LOG_IF\s*\(\s*INFO\s*,", contents):
[email protected]85210652013-11-28 05:50:131163 log_info.append(f.LocalPath())
[email protected]18b466b2013-12-02 22:01:371164
mohan.reddyf21db962014-10-16 12:26:471165 if input_api.re.search(r"\bprintf\(", contents):
[email protected]18b466b2013-12-02 22:01:371166 printf.append(f.LocalPath())
mohan.reddyf21db962014-10-16 12:26:471167 elif input_api.re.search(r"\bfprintf\((stdout|stderr)", contents):
[email protected]85218562013-11-22 07:41:401168 printf.append(f.LocalPath())
1169
1170 if log_info:
1171 return [output_api.PresubmitError(
1172 'These files spam the console log with LOG(INFO):',
1173 items=log_info)]
1174 if printf:
1175 return [output_api.PresubmitError(
1176 'These files spam the console log with printf/fprintf:',
1177 items=printf)]
1178 return []
1179
1180
[email protected]49aa76a2013-12-04 06:59:161181def _CheckForAnonymousVariables(input_api, output_api):
1182 """These types are all expected to hold locks while in scope and
1183 so should never be anonymous (which causes them to be immediately
1184 destroyed)."""
1185 they_who_must_be_named = [
1186 'base::AutoLock',
1187 'base::AutoReset',
1188 'base::AutoUnlock',
1189 'SkAutoAlphaRestore',
1190 'SkAutoBitmapShaderInstall',
1191 'SkAutoBlitterChoose',
1192 'SkAutoBounderCommit',
1193 'SkAutoCallProc',
1194 'SkAutoCanvasRestore',
1195 'SkAutoCommentBlock',
1196 'SkAutoDescriptor',
1197 'SkAutoDisableDirectionCheck',
1198 'SkAutoDisableOvalCheck',
1199 'SkAutoFree',
1200 'SkAutoGlyphCache',
1201 'SkAutoHDC',
1202 'SkAutoLockColors',
1203 'SkAutoLockPixels',
1204 'SkAutoMalloc',
1205 'SkAutoMaskFreeImage',
1206 'SkAutoMutexAcquire',
1207 'SkAutoPathBoundsUpdate',
1208 'SkAutoPDFRelease',
1209 'SkAutoRasterClipValidate',
1210 'SkAutoRef',
1211 'SkAutoTime',
1212 'SkAutoTrace',
1213 'SkAutoUnref',
1214 ]
1215 anonymous = r'(%s)\s*[({]' % '|'.join(they_who_must_be_named)
1216 # bad: base::AutoLock(lock.get());
1217 # not bad: base::AutoLock lock(lock.get());
1218 bad_pattern = input_api.re.compile(anonymous)
1219 # good: new base::AutoLock(lock.get())
1220 good_pattern = input_api.re.compile(r'\bnew\s*' + anonymous)
1221 errors = []
1222
1223 for f in input_api.AffectedFiles():
1224 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
1225 continue
1226 for linenum, line in f.ChangedContents():
1227 if bad_pattern.search(line) and not good_pattern.search(line):
1228 errors.append('%s:%d' % (f.LocalPath(), linenum))
1229
1230 if errors:
1231 return [output_api.PresubmitError(
1232 'These lines create anonymous variables that need to be named:',
1233 items=errors)]
1234 return []
1235
1236
[email protected]5fe0f8742013-11-29 01:04:591237def _CheckCygwinShell(input_api, output_api):
1238 source_file_filter = lambda x: input_api.FilterSourceFile(
1239 x, white_list=(r'.+\.(gyp|gypi)$',))
1240 cygwin_shell = []
1241
1242 for f in input_api.AffectedSourceFiles(source_file_filter):
1243 for linenum, line in f.ChangedContents():
1244 if 'msvs_cygwin_shell' in line:
1245 cygwin_shell.append(f.LocalPath())
1246 break
1247
1248 if cygwin_shell:
1249 return [output_api.PresubmitError(
1250 'These files should not use msvs_cygwin_shell (the default is 0):',
1251 items=cygwin_shell)]
1252 return []
1253
[email protected]85218562013-11-22 07:41:401254
[email protected]999261d2014-03-03 20:08:081255def _CheckUserActionUpdate(input_api, output_api):
1256 """Checks if any new user action has been added."""
[email protected]2f92dec2014-03-07 19:21:521257 if any('actions.xml' == input_api.os_path.basename(f) for f in
[email protected]999261d2014-03-03 20:08:081258 input_api.LocalPaths()):
[email protected]2f92dec2014-03-07 19:21:521259 # If actions.xml is already included in the changelist, the PRESUBMIT
1260 # for actions.xml will do a more complete presubmit check.
[email protected]999261d2014-03-03 20:08:081261 return []
1262
[email protected]999261d2014-03-03 20:08:081263 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm'))
1264 action_re = r'[^a-zA-Z]UserMetricsAction\("([^"]*)'
[email protected]2f92dec2014-03-07 19:21:521265 current_actions = None
[email protected]999261d2014-03-03 20:08:081266 for f in input_api.AffectedFiles(file_filter=file_filter):
1267 for line_num, line in f.ChangedContents():
1268 match = input_api.re.search(action_re, line)
1269 if match:
[email protected]2f92dec2014-03-07 19:21:521270 # Loads contents in tools/metrics/actions/actions.xml to memory. It's
1271 # loaded only once.
1272 if not current_actions:
1273 with open('tools/metrics/actions/actions.xml') as actions_f:
1274 current_actions = actions_f.read()
1275 # Search for the matched user action name in |current_actions|.
[email protected]999261d2014-03-03 20:08:081276 for action_name in match.groups():
[email protected]2f92dec2014-03-07 19:21:521277 action = 'name="{0}"'.format(action_name)
1278 if action not in current_actions:
[email protected]999261d2014-03-03 20:08:081279 return [output_api.PresubmitPromptWarning(
1280 'File %s line %d: %s is missing in '
[email protected]2f92dec2014-03-07 19:21:521281 'tools/metrics/actions/actions.xml. Please run '
1282 'tools/metrics/actions/extract_actions.py to update.'
[email protected]999261d2014-03-03 20:08:081283 % (f.LocalPath(), line_num, action_name))]
1284 return []
1285
1286
[email protected]99171a92014-06-03 08:44:471287def _GetJSONParseError(input_api, filename, eat_comments=True):
1288 try:
1289 contents = input_api.ReadFile(filename)
1290 if eat_comments:
plundblad1f5a4509f2015-07-23 11:31:131291 import sys
1292 original_sys_path = sys.path
1293 try:
1294 sys.path = sys.path + [input_api.os_path.join(
1295 input_api.PresubmitLocalPath(),
1296 'tools', 'json_comment_eater')]
1297 import json_comment_eater
1298 finally:
1299 sys.path = original_sys_path
1300 contents = json_comment_eater.Nom(contents)
[email protected]99171a92014-06-03 08:44:471301
1302 input_api.json.loads(contents)
1303 except ValueError as e:
1304 return e
1305 return None
1306
1307
1308def _GetIDLParseError(input_api, filename):
1309 try:
1310 contents = input_api.ReadFile(filename)
1311 idl_schema = input_api.os_path.join(
1312 input_api.PresubmitLocalPath(),
1313 'tools', 'json_schema_compiler', 'idl_schema.py')
1314 process = input_api.subprocess.Popen(
1315 [input_api.python_executable, idl_schema],
1316 stdin=input_api.subprocess.PIPE,
1317 stdout=input_api.subprocess.PIPE,
1318 stderr=input_api.subprocess.PIPE,
1319 universal_newlines=True)
1320 (_, error) = process.communicate(input=contents)
1321 return error or None
1322 except ValueError as e:
1323 return e
1324
1325
1326def _CheckParseErrors(input_api, output_api):
1327 """Check that IDL and JSON files do not contain syntax errors."""
1328 actions = {
1329 '.idl': _GetIDLParseError,
1330 '.json': _GetJSONParseError,
1331 }
1332 # These paths contain test data and other known invalid JSON files.
1333 excluded_patterns = [
joaodasilva718f87672014-08-30 09:25:491334 r'test[\\\/]data[\\\/]',
1335 r'^components[\\\/]policy[\\\/]resources[\\\/]policy_templates\.json$',
[email protected]99171a92014-06-03 08:44:471336 ]
1337 # Most JSON files are preprocessed and support comments, but these do not.
1338 json_no_comments_patterns = [
joaodasilva718f87672014-08-30 09:25:491339 r'^testing[\\\/]',
[email protected]99171a92014-06-03 08:44:471340 ]
1341 # Only run IDL checker on files in these directories.
1342 idl_included_patterns = [
joaodasilva718f87672014-08-30 09:25:491343 r'^chrome[\\\/]common[\\\/]extensions[\\\/]api[\\\/]',
1344 r'^extensions[\\\/]common[\\\/]api[\\\/]',
[email protected]99171a92014-06-03 08:44:471345 ]
1346
1347 def get_action(affected_file):
1348 filename = affected_file.LocalPath()
1349 return actions.get(input_api.os_path.splitext(filename)[1])
1350
1351 def MatchesFile(patterns, path):
1352 for pattern in patterns:
1353 if input_api.re.search(pattern, path):
1354 return True
1355 return False
1356
1357 def FilterFile(affected_file):
1358 action = get_action(affected_file)
1359 if not action:
1360 return False
1361 path = affected_file.LocalPath()
1362
1363 if MatchesFile(excluded_patterns, path):
1364 return False
1365
1366 if (action == _GetIDLParseError and
1367 not MatchesFile(idl_included_patterns, path)):
1368 return False
1369 return True
1370
1371 results = []
1372 for affected_file in input_api.AffectedFiles(
1373 file_filter=FilterFile, include_deletes=False):
1374 action = get_action(affected_file)
1375 kwargs = {}
1376 if (action == _GetJSONParseError and
1377 MatchesFile(json_no_comments_patterns, affected_file.LocalPath())):
1378 kwargs['eat_comments'] = False
1379 parse_error = action(input_api,
1380 affected_file.AbsoluteLocalPath(),
1381 **kwargs)
1382 if parse_error:
1383 results.append(output_api.PresubmitError('%s could not be parsed: %s' %
1384 (affected_file.LocalPath(), parse_error)))
1385 return results
1386
1387
[email protected]760deea2013-12-10 19:33:491388def _CheckJavaStyle(input_api, output_api):
1389 """Runs checkstyle on changed java files and returns errors if any exist."""
mohan.reddyf21db962014-10-16 12:26:471390 import sys
[email protected]760deea2013-12-10 19:33:491391 original_sys_path = sys.path
1392 try:
1393 sys.path = sys.path + [input_api.os_path.join(
1394 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkstyle')]
1395 import checkstyle
1396 finally:
1397 # Restore sys.path to what it was before.
1398 sys.path = original_sys_path
1399
1400 return checkstyle.RunCheckstyle(
davileen72d76532015-01-20 22:30:091401 input_api, output_api, 'tools/android/checkstyle/chromium-style-5.0.xml',
newtd8b7d30e92015-01-23 18:10:511402 black_list=_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
[email protected]760deea2013-12-10 19:33:491403
1404
dchenge07de812016-06-20 19:27:171405def _CheckIpcOwners(input_api, output_api):
1406 """Checks that affected files involving IPC have an IPC OWNERS rule.
1407
1408 Whether or not a file affects IPC is determined by a simple whitelist of
1409 filename patterns."""
1410 file_patterns = [
1411 '*_messages.cc',
1412 '*_messages*.h',
1413 '*_param_traits*.*',
1414 '*.mojom',
1415 '*_struct_traits*.*',
1416 '*_type_converter*.*',
1417 # Blink uses a different file naming convention
1418 '*StructTraits*.*',
1419 '*TypeConverter*.*',
1420 ]
1421
1422 # Dictionary mapping an OWNERS file path to Patterns.
1423 # Patterns is a dictionary mapping glob patterns (suitable for use in per-file
1424 # rules ) to a PatternEntry.
1425 # PatternEntry is a dictionary with two keys:
1426 # - 'files': the files that are matched by this pattern
1427 # - 'rules': the per-file rules needed for this pattern
1428 # For example, if we expect OWNERS file to contain rules for *.mojom and
1429 # *_struct_traits*.*, Patterns might look like this:
1430 # {
1431 # '*.mojom': {
1432 # 'files': ...,
1433 # 'rules': [
1434 # 'per-file *.mojom=set noparent',
1435 # 'per-file *.mojom=file://ipc/SECURITY_OWNERS',
1436 # ],
1437 # },
1438 # '*_struct_traits*.*': {
1439 # 'files': ...,
1440 # 'rules': [
1441 # 'per-file *_struct_traits*.*=set noparent',
1442 # 'per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS',
1443 # ],
1444 # },
1445 # }
1446 to_check = {}
1447
1448 # Iterate through the affected files to see what we actually need to check
1449 # for. We should only nag patch authors about per-file rules if a file in that
1450 # directory would match that pattern. If a directory only contains *.mojom
1451 # files and no *_messages*.h files, we should only nag about rules for
1452 # *.mojom files.
rockot51249332016-06-23 16:32:251453 for f in input_api.change.AffectedFiles(include_deletes=False):
dchenge07de812016-06-20 19:27:171454 for pattern in file_patterns:
1455 if input_api.fnmatch.fnmatch(
1456 input_api.os_path.basename(f.LocalPath()), pattern):
1457 owners_file = input_api.os_path.join(
1458 input_api.os_path.dirname(f.LocalPath()), 'OWNERS')
1459 if owners_file not in to_check:
1460 to_check[owners_file] = {}
1461 if pattern not in to_check[owners_file]:
1462 to_check[owners_file][pattern] = {
1463 'files': [],
1464 'rules': [
1465 'per-file %s=set noparent' % pattern,
1466 'per-file %s=file://ipc/SECURITY_OWNERS' % pattern,
1467 ]
1468 }
1469 to_check[owners_file][pattern]['files'].append(f)
1470 break
1471
1472 # Now go through the OWNERS files we collected, filtering out rules that are
1473 # already present in that OWNERS file.
1474 for owners_file, patterns in to_check.iteritems():
1475 try:
1476 with file(owners_file) as f:
1477 lines = set(f.read().splitlines())
1478 for entry in patterns.itervalues():
1479 entry['rules'] = [rule for rule in entry['rules'] if rule not in lines
1480 ]
1481 except IOError:
1482 # No OWNERS file, so all the rules are definitely missing.
1483 continue
1484
1485 # All the remaining lines weren't found in OWNERS files, so emit an error.
1486 errors = []
1487 for owners_file, patterns in to_check.iteritems():
1488 missing_lines = []
1489 files = []
1490 for pattern, entry in patterns.iteritems():
1491 missing_lines.extend(entry['rules'])
1492 files.extend([' %s' % f.LocalPath() for f in entry['files']])
1493 if missing_lines:
1494 errors.append(
1495 '%s is missing the following lines:\n\n%s\n\nfor changed files:\n%s' %
1496 (owners_file, '\n'.join(missing_lines), '\n'.join(files)))
1497
1498 results = []
1499 if errors:
1500 results.append(output_api.PresubmitError(
1501 'Found changes to IPC files without a security OWNER!',
1502 long_text='\n\n'.join(errors)))
1503
1504 return results
1505
1506
dskiba88634f4e2015-08-14 23:03:291507def _CheckAndroidToastUsage(input_api, output_api):
1508 """Checks that code uses org.chromium.ui.widget.Toast instead of
1509 android.widget.Toast (Chromium Toast doesn't force hardware
1510 acceleration on low-end devices, saving memory).
1511 """
1512 toast_import_pattern = input_api.re.compile(
1513 r'^import android\.widget\.Toast;$')
1514
1515 errors = []
1516
1517 sources = lambda affected_file: input_api.FilterSourceFile(
1518 affected_file,
1519 black_list=(_EXCLUDED_PATHS +
1520 _TEST_CODE_EXCLUDED_PATHS +
1521 input_api.DEFAULT_BLACK_LIST +
1522 (r'^chromecast[\\\/].*',
1523 r'^remoting[\\\/].*')),
1524 white_list=(r'.*\.java$',))
1525
1526 for f in input_api.AffectedSourceFiles(sources):
1527 for line_num, line in f.ChangedContents():
1528 if toast_import_pattern.search(line):
1529 errors.append("%s:%d" % (f.LocalPath(), line_num))
1530
1531 results = []
1532
1533 if errors:
1534 results.append(output_api.PresubmitError(
1535 'android.widget.Toast usage is detected. Android toasts use hardware'
1536 ' acceleration, and can be\ncostly on low-end devices. Please use'
1537 ' org.chromium.ui.widget.Toast instead.\n'
1538 'Contact [email protected] if you have any questions.',
1539 errors))
1540
1541 return results
1542
1543
dgnaa68d5e2015-06-10 10:08:221544def _CheckAndroidCrLogUsage(input_api, output_api):
1545 """Checks that new logs using org.chromium.base.Log:
1546 - Are using 'TAG' as variable name for the tags (warn)
dgn38736db2015-09-18 19:20:511547 - Are using a tag that is shorter than 20 characters (error)
dgnaa68d5e2015-06-10 10:08:221548 """
pkotwicza1dd0b002016-05-16 14:41:041549
1550 # Do not check format of logs in //chrome/android/webapk because
1551 # //chrome/android/webapk cannot depend on //base
1552 cr_log_check_excluded_paths = [
1553 r"^chrome[\\\/]android[\\\/]webapk[\\\/].*",
1554 ]
1555
dgnaa68d5e2015-06-10 10:08:221556 cr_log_import_pattern = input_api.re.compile(
dgn87d9fb62015-06-12 09:15:121557 r'^import org\.chromium\.base\.Log;$', input_api.re.MULTILINE)
1558 class_in_base_pattern = input_api.re.compile(
1559 r'^package org\.chromium\.base;$', input_api.re.MULTILINE)
1560 has_some_log_import_pattern = input_api.re.compile(
1561 r'^import .*\.Log;$', input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221562 # Extract the tag from lines like `Log.d(TAG, "*");` or `Log.d("TAG", "*");`
dgn87d9fb62015-06-12 09:15:121563 log_call_pattern = input_api.re.compile(r'^\s*Log\.\w\((?P<tag>\"?\w+\"?)\,')
dgnaa68d5e2015-06-10 10:08:221564 log_decl_pattern = input_api.re.compile(
dgn38736db2015-09-18 19:20:511565 r'^\s*private static final String TAG = "(?P<name>(.*))";',
dgnaa68d5e2015-06-10 10:08:221566 input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221567
Vincent Scheib16d7b272015-09-15 18:09:071568 REF_MSG = ('See docs/android_logging.md '
dgnaa68d5e2015-06-10 10:08:221569 'or contact [email protected] for more info.')
pkotwicza1dd0b002016-05-16 14:41:041570 sources = lambda x: input_api.FilterSourceFile(x, white_list=(r'.*\.java$',),
1571 black_list=cr_log_check_excluded_paths)
dgn87d9fb62015-06-12 09:15:121572
dgnaa68d5e2015-06-10 10:08:221573 tag_decl_errors = []
1574 tag_length_errors = []
dgn87d9fb62015-06-12 09:15:121575 tag_errors = []
dgn38736db2015-09-18 19:20:511576 tag_with_dot_errors = []
dgn87d9fb62015-06-12 09:15:121577 util_log_errors = []
dgnaa68d5e2015-06-10 10:08:221578
1579 for f in input_api.AffectedSourceFiles(sources):
1580 file_content = input_api.ReadFile(f)
1581 has_modified_logs = False
1582
1583 # Per line checks
dgn87d9fb62015-06-12 09:15:121584 if (cr_log_import_pattern.search(file_content) or
1585 (class_in_base_pattern.search(file_content) and
1586 not has_some_log_import_pattern.search(file_content))):
1587 # Checks to run for files using cr log
dgnaa68d5e2015-06-10 10:08:221588 for line_num, line in f.ChangedContents():
1589
1590 # Check if the new line is doing some logging
dgn87d9fb62015-06-12 09:15:121591 match = log_call_pattern.search(line)
dgnaa68d5e2015-06-10 10:08:221592 if match:
1593 has_modified_logs = True
1594
1595 # Make sure it uses "TAG"
1596 if not match.group('tag') == 'TAG':
1597 tag_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgn87d9fb62015-06-12 09:15:121598 else:
1599 # Report non cr Log function calls in changed lines
1600 for line_num, line in f.ChangedContents():
1601 if log_call_pattern.search(line):
1602 util_log_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgnaa68d5e2015-06-10 10:08:221603
1604 # Per file checks
1605 if has_modified_logs:
1606 # Make sure the tag is using the "cr" prefix and is not too long
1607 match = log_decl_pattern.search(file_content)
dgn38736db2015-09-18 19:20:511608 tag_name = match.group('name') if match else None
1609 if not tag_name:
dgnaa68d5e2015-06-10 10:08:221610 tag_decl_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511611 elif len(tag_name) > 20:
dgnaa68d5e2015-06-10 10:08:221612 tag_length_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511613 elif '.' in tag_name:
1614 tag_with_dot_errors.append(f.LocalPath())
dgnaa68d5e2015-06-10 10:08:221615
1616 results = []
1617 if tag_decl_errors:
1618 results.append(output_api.PresubmitPromptWarning(
1619 'Please define your tags using the suggested format: .\n'
dgn38736db2015-09-18 19:20:511620 '"private static final String TAG = "<package tag>".\n'
1621 'They will be prepended with "cr_" automatically.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221622 tag_decl_errors))
1623
1624 if tag_length_errors:
1625 results.append(output_api.PresubmitError(
1626 'The tag length is restricted by the system to be at most '
dgn38736db2015-09-18 19:20:511627 '20 characters.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221628 tag_length_errors))
1629
1630 if tag_errors:
1631 results.append(output_api.PresubmitPromptWarning(
1632 'Please use a variable named "TAG" for your log tags.\n' + REF_MSG,
1633 tag_errors))
1634
dgn87d9fb62015-06-12 09:15:121635 if util_log_errors:
dgn4401aa52015-04-29 16:26:171636 results.append(output_api.PresubmitPromptWarning(
dgn87d9fb62015-06-12 09:15:121637 'Please use org.chromium.base.Log for new logs.\n' + REF_MSG,
1638 util_log_errors))
1639
dgn38736db2015-09-18 19:20:511640 if tag_with_dot_errors:
1641 results.append(output_api.PresubmitPromptWarning(
1642 'Dot in log tags cause them to be elided in crash reports.\n' + REF_MSG,
1643 tag_with_dot_errors))
1644
dgn4401aa52015-04-29 16:26:171645 return results
1646
1647
agrieve7b6479d82015-10-07 14:24:221648def _CheckAndroidNewMdpiAssetLocation(input_api, output_api):
1649 """Checks if MDPI assets are placed in a correct directory."""
1650 file_filter = lambda f: (f.LocalPath().endswith('.png') and
1651 ('/res/drawable/' in f.LocalPath() or
1652 '/res/drawable-ldrtl/' in f.LocalPath()))
1653 errors = []
1654 for f in input_api.AffectedFiles(include_deletes=False,
1655 file_filter=file_filter):
1656 errors.append(' %s' % f.LocalPath())
1657
1658 results = []
1659 if errors:
1660 results.append(output_api.PresubmitError(
1661 'MDPI assets should be placed in /res/drawable-mdpi/ or '
1662 '/res/drawable-ldrtl-mdpi/\ninstead of /res/drawable/ and'
1663 '/res/drawable-ldrtl/.\n'
1664 'Contact [email protected] if you have questions.', errors))
1665 return results
1666
1667
agrievef32bcc72016-04-04 14:57:401668class PydepsChecker(object):
1669 def __init__(self, input_api, pydeps_files):
1670 self._file_cache = {}
1671 self._input_api = input_api
1672 self._pydeps_files = pydeps_files
1673
1674 def _LoadFile(self, path):
1675 """Returns the list of paths within a .pydeps file relative to //."""
1676 if path not in self._file_cache:
1677 with open(path) as f:
1678 self._file_cache[path] = f.read()
1679 return self._file_cache[path]
1680
1681 def _ComputeNormalizedPydepsEntries(self, pydeps_path):
1682 """Returns an interable of paths within the .pydep, relativized to //."""
1683 os_path = self._input_api.os_path
1684 pydeps_dir = os_path.dirname(pydeps_path)
1685 entries = (l.rstrip() for l in self._LoadFile(pydeps_path).splitlines()
1686 if not l.startswith('*'))
1687 return (os_path.normpath(os_path.join(pydeps_dir, e)) for e in entries)
1688
1689 def _CreateFilesToPydepsMap(self):
1690 """Returns a map of local_path -> list_of_pydeps."""
1691 ret = {}
1692 for pydep_local_path in self._pydeps_files:
1693 for path in self._ComputeNormalizedPydepsEntries(pydep_local_path):
1694 ret.setdefault(path, []).append(pydep_local_path)
1695 return ret
1696
1697 def ComputeAffectedPydeps(self):
1698 """Returns an iterable of .pydeps files that might need regenerating."""
1699 affected_pydeps = set()
1700 file_to_pydeps_map = None
1701 for f in self._input_api.AffectedFiles(include_deletes=True):
1702 local_path = f.LocalPath()
1703 if local_path == 'DEPS':
1704 return self._pydeps_files
1705 elif local_path.endswith('.pydeps'):
1706 if local_path in self._pydeps_files:
1707 affected_pydeps.add(local_path)
1708 elif local_path.endswith('.py'):
1709 if file_to_pydeps_map is None:
1710 file_to_pydeps_map = self._CreateFilesToPydepsMap()
1711 affected_pydeps.update(file_to_pydeps_map.get(local_path, ()))
1712 return affected_pydeps
1713
1714 def DetermineIfStale(self, pydeps_path):
1715 """Runs print_python_deps.py to see if the files is stale."""
1716 old_pydeps_data = self._LoadFile(pydeps_path).splitlines()
1717 cmd = old_pydeps_data[1][1:].strip()
1718 new_pydeps_data = self._input_api.subprocess.check_output(
1719 cmd + ' --output ""', shell=True)
1720 if old_pydeps_data[2:] != new_pydeps_data.splitlines()[2:]:
1721 return cmd
1722
1723
1724def _CheckPydepsNeedsUpdating(input_api, output_api, checker_for_tests=None):
1725 """Checks if a .pydeps file needs to be regenerated."""
agrievebb9c5b472016-04-22 15:13:001726 # This check is mainly for Android, and involves paths not only in the
agrieve9bc4200b2016-05-04 16:33:281727 # PRESUBMIT.py, but also in the .pydeps files. It doesn't work on Windows and
1728 # Mac, so skip it on other platforms.
1729 if input_api.platform != 'linux2':
agrievebb9c5b472016-04-22 15:13:001730 return []
agrievef32bcc72016-04-04 14:57:401731 # TODO(agrieve): Update when there's a better way to detect this: crbug/570091
1732 is_android = input_api.os_path.exists('third_party/android_tools')
1733 pydeps_files = _ALL_PYDEPS_FILES if is_android else _GENERIC_PYDEPS_FILES
1734 results = []
1735 # First, check for new / deleted .pydeps.
1736 for f in input_api.AffectedFiles(include_deletes=True):
1737 if f.LocalPath().endswith('.pydeps'):
1738 if f.Action() == 'D' and f.LocalPath() in _ALL_PYDEPS_FILES:
1739 results.append(output_api.PresubmitError(
1740 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
1741 'remove %s' % f.LocalPath()))
1742 elif f.Action() != 'D' and f.LocalPath() not in _ALL_PYDEPS_FILES:
1743 results.append(output_api.PresubmitError(
1744 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
1745 'include %s' % f.LocalPath()))
1746
1747 if results:
1748 return results
1749
1750 checker = checker_for_tests or PydepsChecker(input_api, pydeps_files)
1751
1752 for pydep_path in checker.ComputeAffectedPydeps():
1753 try:
1754 cmd = checker.DetermineIfStale(pydep_path)
1755 if cmd:
1756 results.append(output_api.PresubmitError(
1757 'File is stale: %s\nTo regenerate, run:\n\n %s' %
1758 (pydep_path, cmd)))
1759 except input_api.subprocess.CalledProcessError as error:
1760 return [output_api.PresubmitError('Error running: %s' % error.cmd,
1761 long_text=error.output)]
1762
1763 return results
1764
1765
mnaganov9b9b1fe82014-12-11 16:30:361766def _CheckForCopyrightedCode(input_api, output_api):
1767 """Verifies that newly added code doesn't contain copyrighted material
1768 and is properly licensed under the standard Chromium license.
1769
1770 As there can be false positives, we maintain a whitelist file. This check
1771 also verifies that the whitelist file is up to date.
1772 """
1773 import sys
1774 original_sys_path = sys.path
1775 try:
1776 sys.path = sys.path + [input_api.os_path.join(
mnaganovf771be4a2015-06-12 18:13:221777 input_api.PresubmitLocalPath(), 'tools')]
1778 from copyright_scanner import copyright_scanner
mnaganov9b9b1fe82014-12-11 16:30:361779 finally:
1780 # Restore sys.path to what it was before.
1781 sys.path = original_sys_path
1782
1783 return copyright_scanner.ScanAtPresubmit(input_api, output_api)
1784
1785
glidere61efad2015-02-18 17:39:431786def _CheckSingletonInHeaders(input_api, output_api):
1787 """Checks to make sure no header files have |Singleton<|."""
1788 def FileFilter(affected_file):
1789 # It's ok for base/memory/singleton.h to have |Singleton<|.
1790 black_list = (_EXCLUDED_PATHS +
1791 input_api.DEFAULT_BLACK_LIST +
1792 (r"^base[\\\/]memory[\\\/]singleton\.h$",))
1793 return input_api.FilterSourceFile(affected_file, black_list=black_list)
1794
sergeyu34d21222015-09-16 00:11:441795 pattern = input_api.re.compile(r'(?<!class\sbase::)Singleton\s*<')
glidere61efad2015-02-18 17:39:431796 files = []
1797 for f in input_api.AffectedSourceFiles(FileFilter):
1798 if (f.LocalPath().endswith('.h') or f.LocalPath().endswith('.hxx') or
1799 f.LocalPath().endswith('.hpp') or f.LocalPath().endswith('.inl')):
1800 contents = input_api.ReadFile(f)
1801 for line in contents.splitlines(False):
oysteinec430ad42015-10-22 20:55:241802 if (not line.lstrip().startswith('//') and # Strip C++ comment.
glidere61efad2015-02-18 17:39:431803 pattern.search(line)):
1804 files.append(f)
1805 break
1806
1807 if files:
yolandyandaabc6d2016-04-18 18:29:391808 return [output_api.PresubmitError(
sergeyu34d21222015-09-16 00:11:441809 'Found base::Singleton<T> in the following header files.\n' +
glidere61efad2015-02-18 17:39:431810 'Please move them to an appropriate source file so that the ' +
1811 'template gets instantiated in a single compilation unit.',
1812 files) ]
1813 return []
1814
1815
dbeam37e8e7402016-02-10 22:58:201816def _CheckNoDeprecatedCompiledResourcesGYP(input_api, output_api):
1817 """Checks for old style compiled_resources.gyp files."""
1818 is_compiled_resource = lambda fp: fp.endswith('compiled_resources.gyp')
1819
1820 added_compiled_resources = filter(is_compiled_resource, [
1821 f.LocalPath() for f in input_api.AffectedFiles() if f.Action() == 'A'
1822 ])
1823
1824 if not added_compiled_resources:
1825 return []
1826
1827 return [output_api.PresubmitError(
1828 "Found new compiled_resources.gyp files:\n%s\n\n"
1829 "compiled_resources.gyp files are deprecated,\n"
michaelpgdb9985072016-02-24 19:13:551830 "please use compiled_resources2.gyp instead:\n"
1831 "https://chromium.googlesource.com/chromium/src/+/master/docs/closure_compilation.md"
1832 %
dbeam37e8e7402016-02-10 22:58:201833 "\n".join(added_compiled_resources))]
1834
1835
[email protected]fd20b902014-05-09 02:14:531836_DEPRECATED_CSS = [
1837 # Values
1838 ( "-webkit-box", "flex" ),
1839 ( "-webkit-inline-box", "inline-flex" ),
1840 ( "-webkit-flex", "flex" ),
1841 ( "-webkit-inline-flex", "inline-flex" ),
1842 ( "-webkit-min-content", "min-content" ),
1843 ( "-webkit-max-content", "max-content" ),
1844
1845 # Properties
1846 ( "-webkit-background-clip", "background-clip" ),
1847 ( "-webkit-background-origin", "background-origin" ),
1848 ( "-webkit-background-size", "background-size" ),
1849 ( "-webkit-box-shadow", "box-shadow" ),
1850
1851 # Functions
1852 ( "-webkit-gradient", "gradient" ),
1853 ( "-webkit-repeating-gradient", "repeating-gradient" ),
1854 ( "-webkit-linear-gradient", "linear-gradient" ),
1855 ( "-webkit-repeating-linear-gradient", "repeating-linear-gradient" ),
1856 ( "-webkit-radial-gradient", "radial-gradient" ),
1857 ( "-webkit-repeating-radial-gradient", "repeating-radial-gradient" ),
1858]
1859
1860def _CheckNoDeprecatedCSS(input_api, output_api):
1861 """ Make sure that we don't use deprecated CSS
[email protected]9a48e3f82014-05-22 00:06:251862 properties, functions or values. Our external
mdjonesae0286c32015-06-10 18:10:341863 documentation and iOS CSS for dom distiller
1864 (reader mode) are ignored by the hooks as it
[email protected]9a48e3f82014-05-22 00:06:251865 needs to be consumed by WebKit. """
[email protected]fd20b902014-05-09 02:14:531866 results = []
dbeam070cfe62014-10-22 06:44:021867 file_inclusion_pattern = (r".+\.css$",)
[email protected]9a48e3f82014-05-22 00:06:251868 black_list = (_EXCLUDED_PATHS +
1869 _TEST_CODE_EXCLUDED_PATHS +
1870 input_api.DEFAULT_BLACK_LIST +
1871 (r"^chrome/common/extensions/docs",
1872 r"^chrome/docs",
mdjonesae0286c32015-06-10 18:10:341873 r"^components/dom_distiller/core/css/distilledpage_ios.css",
sdefresneda218472015-12-07 18:38:051874 r"^components/flags_ui/resources/apple_flags.css",
sdefresne6308d7f2016-02-15 09:38:441875 r"^components/neterror/resources/neterror.css",
[email protected]9a48e3f82014-05-22 00:06:251876 r"^native_client_sdk"))
1877 file_filter = lambda f: input_api.FilterSourceFile(
1878 f, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]fd20b902014-05-09 02:14:531879 for fpath in input_api.AffectedFiles(file_filter=file_filter):
1880 for line_num, line in fpath.ChangedContents():
1881 for (deprecated_value, value) in _DEPRECATED_CSS:
dbeam070cfe62014-10-22 06:44:021882 if deprecated_value in line:
[email protected]fd20b902014-05-09 02:14:531883 results.append(output_api.PresubmitError(
1884 "%s:%d: Use of deprecated CSS %s, use %s instead" %
1885 (fpath.LocalPath(), line_num, deprecated_value, value)))
1886 return results
1887
mohan.reddyf21db962014-10-16 12:26:471888
dbeam070cfe62014-10-22 06:44:021889_DEPRECATED_JS = [
1890 ( "__lookupGetter__", "Object.getOwnPropertyDescriptor" ),
1891 ( "__defineGetter__", "Object.defineProperty" ),
1892 ( "__defineSetter__", "Object.defineProperty" ),
1893]
1894
1895def _CheckNoDeprecatedJS(input_api, output_api):
1896 """Make sure that we don't use deprecated JS in Chrome code."""
1897 results = []
1898 file_inclusion_pattern = (r".+\.js$",) # TODO(dbeam): .html?
1899 black_list = (_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
1900 input_api.DEFAULT_BLACK_LIST)
1901 file_filter = lambda f: input_api.FilterSourceFile(
1902 f, white_list=file_inclusion_pattern, black_list=black_list)
1903 for fpath in input_api.AffectedFiles(file_filter=file_filter):
1904 for lnum, line in fpath.ChangedContents():
1905 for (deprecated, replacement) in _DEPRECATED_JS:
1906 if deprecated in line:
1907 results.append(output_api.PresubmitError(
1908 "%s:%d: Use of deprecated JS %s, use %s instead" %
1909 (fpath.LocalPath(), lnum, deprecated, replacement)))
1910 return results
1911
1912
dgnaa68d5e2015-06-10 10:08:221913def _AndroidSpecificOnUploadChecks(input_api, output_api):
1914 """Groups checks that target android code."""
1915 results = []
dgnaa68d5e2015-06-10 10:08:221916 results.extend(_CheckAndroidCrLogUsage(input_api, output_api))
agrieve7b6479d82015-10-07 14:24:221917 results.extend(_CheckAndroidNewMdpiAssetLocation(input_api, output_api))
dskiba88634f4e2015-08-14 23:03:291918 results.extend(_CheckAndroidToastUsage(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:221919 return results
1920
1921
[email protected]22c9bd72011-03-27 16:47:391922def _CommonChecks(input_api, output_api):
1923 """Checks common to both upload and commit."""
1924 results = []
1925 results.extend(input_api.canned_checks.PanProjectChecks(
[email protected]3de922f2013-12-20 13:27:381926 input_api, output_api,
1927 excluded_paths=_EXCLUDED_PATHS + _TESTRUNNER_PATHS))
[email protected]66daa702011-05-28 14:41:461928 results.extend(_CheckAuthorizedAuthor(input_api, output_api))
[email protected]55459852011-08-10 15:17:191929 results.extend(
[email protected]760deea2013-12-10 19:33:491930 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api))
[email protected]10689ca2011-09-02 02:31:541931 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
[email protected]72df4e782012-06-21 16:28:181932 results.extend(_CheckNoUNIT_TESTInSourceFiles(input_api, output_api))
danakj61c1aa22015-10-26 19:55:521933 results.extend(_CheckDCHECK_IS_ONHasBraces(input_api, output_api))
[email protected]8ea5d4b2011-09-13 21:49:221934 results.extend(_CheckNoNewWStrings(input_api, output_api))
[email protected]2a8ac9c2011-10-19 17:20:441935 results.extend(_CheckNoDEPSGIT(input_api, output_api))
[email protected]127f18ec2012-06-16 05:05:591936 results.extend(_CheckNoBannedFunctions(input_api, output_api))
[email protected]6c063c62012-07-11 19:11:061937 results.extend(_CheckNoPragmaOnce(input_api, output_api))
[email protected]e7479052012-09-19 00:26:121938 results.extend(_CheckNoTrinaryTrueFalse(input_api, output_api))
[email protected]55f9f382012-07-31 11:02:181939 results.extend(_CheckUnwantedDependencies(input_api, output_api))
[email protected]fbcafe5a2012-08-08 15:31:221940 results.extend(_CheckFilePermissions(input_api, output_api))
[email protected]c8278b32012-10-30 20:35:491941 results.extend(_CheckNoAuraWindowPropertyHInHeaders(input_api, output_api))
[email protected]2309b0fa02012-11-16 12:18:271942 results.extend(_CheckIncludeOrder(input_api, output_api))
[email protected]70ca77752012-11-20 03:45:031943 results.extend(_CheckForVersionControlConflicts(input_api, output_api))
[email protected]b8079ae4a2012-12-05 19:56:491944 results.extend(_CheckPatchFiles(input_api, output_api))
[email protected]06e6d0ff2012-12-11 01:36:441945 results.extend(_CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api))
[email protected]d2530012013-01-25 16:39:271946 results.extend(_CheckNoAbbreviationInPngFileName(input_api, output_api))
[email protected]b00342e7f2013-03-26 16:21:541947 results.extend(_CheckForInvalidOSMacros(input_api, output_api))
lliabraa35bab3932014-10-01 12:16:441948 results.extend(_CheckForInvalidIfDefinedMacros(input_api, output_api))
yolandyandaabc6d2016-04-18 18:29:391949 results.extend(_CheckFlakyTestUsage(input_api, output_api))
[email protected]e871964c2013-05-13 14:14:551950 results.extend(_CheckAddedDepsHaveTargetApprovals(input_api, output_api))
[email protected]9f919cc2013-07-31 03:04:041951 results.extend(
1952 input_api.canned_checks.CheckChangeHasNoTabs(
1953 input_api,
1954 output_api,
1955 source_file_filter=lambda x: x.LocalPath().endswith('.grd')))
[email protected]85218562013-11-22 07:41:401956 results.extend(_CheckSpamLogging(input_api, output_api))
[email protected]49aa76a2013-12-04 06:59:161957 results.extend(_CheckForAnonymousVariables(input_api, output_api))
[email protected]5fe0f8742013-11-29 01:04:591958 results.extend(_CheckCygwinShell(input_api, output_api))
[email protected]999261d2014-03-03 20:08:081959 results.extend(_CheckUserActionUpdate(input_api, output_api))
[email protected]fd20b902014-05-09 02:14:531960 results.extend(_CheckNoDeprecatedCSS(input_api, output_api))
dbeam070cfe62014-10-22 06:44:021961 results.extend(_CheckNoDeprecatedJS(input_api, output_api))
[email protected]99171a92014-06-03 08:44:471962 results.extend(_CheckParseErrors(input_api, output_api))
mlamouria82272622014-09-16 18:45:041963 results.extend(_CheckForIPCRules(input_api, output_api))
mnaganov9b9b1fe82014-12-11 16:30:361964 results.extend(_CheckForCopyrightedCode(input_api, output_api))
mostynbb639aca52015-01-07 20:31:231965 results.extend(_CheckForWindowsLineEndings(input_api, output_api))
glidere61efad2015-02-18 17:39:431966 results.extend(_CheckSingletonInHeaders(input_api, output_api))
dbeam37e8e7402016-02-10 22:58:201967 results.extend(_CheckNoDeprecatedCompiledResourcesGYP(input_api, output_api))
agrievef32bcc72016-04-04 14:57:401968 results.extend(_CheckPydepsNeedsUpdating(input_api, output_api))
wnwenbdc444e2016-05-25 13:44:151969 results.extend(_CheckJavaStyle(input_api, output_api))
dchenge07de812016-06-20 19:27:171970 results.extend(_CheckIpcOwners(input_api, output_api))
[email protected]2299dcf2012-11-15 19:56:241971
1972 if any('PRESUBMIT.py' == f.LocalPath() for f in input_api.AffectedFiles()):
1973 results.extend(input_api.canned_checks.RunUnitTestsInDirectory(
1974 input_api, output_api,
1975 input_api.PresubmitLocalPath(),
[email protected]6be63382013-01-21 15:42:381976 whitelist=[r'^PRESUBMIT_test\.py$']))
[email protected]22c9bd72011-03-27 16:47:391977 return results
[email protected]1f7b4172010-01-28 01:17:341978
[email protected]b337cb5b2011-01-23 21:24:051979
[email protected]66daa702011-05-28 14:41:461980def _CheckAuthorizedAuthor(input_api, output_api):
1981 """For non-googler/chromites committers, verify the author's email address is
1982 in AUTHORS.
1983 """
1984 author = input_api.change.author_email
[email protected]9bb9cb82011-06-13 20:43:011985 if not author:
1986 input_api.logging.info('No author, skipping AUTHOR check')
[email protected]66daa702011-05-28 14:41:461987 return []
[email protected]c99663292011-05-31 19:46:081988 authors_path = input_api.os_path.join(
[email protected]66daa702011-05-28 14:41:461989 input_api.PresubmitLocalPath(), 'AUTHORS')
1990 valid_authors = (
1991 input_api.re.match(r'[^#]+\s+\<(.+?)\>\s*$', line)
1992 for line in open(authors_path))
[email protected]ac54b132011-06-06 18:11:181993 valid_authors = [item.group(1).lower() for item in valid_authors if item]
dchenge07de812016-06-20 19:27:171994 if not any(input_api.fnmatch.fnmatch(author.lower(), valid)
1995 for valid in valid_authors):
[email protected]5861efb2013-01-07 18:33:231996 input_api.logging.info('Valid authors are %s', ', '.join(valid_authors))
[email protected]66daa702011-05-28 14:41:461997 return [output_api.PresubmitPromptWarning(
1998 ('%s is not in AUTHORS file. If you are a new contributor, please visit'
1999 '\n'
2000 'http://www.chromium.org/developers/contributing-code and read the '
2001 '"Legal" section\n'
2002 'If you are a chromite, verify the contributor signed the CLA.') %
2003 author)]
2004 return []
2005
2006
[email protected]b8079ae4a2012-12-05 19:56:492007def _CheckPatchFiles(input_api, output_api):
2008 problems = [f.LocalPath() for f in input_api.AffectedFiles()
2009 if f.LocalPath().endswith(('.orig', '.rej'))]
2010 if problems:
2011 return [output_api.PresubmitError(
2012 "Don't commit .rej and .orig files.", problems)]
[email protected]2fdd1f362013-01-16 03:56:032013 else:
2014 return []
[email protected]b8079ae4a2012-12-05 19:56:492015
2016
[email protected]b00342e7f2013-03-26 16:21:542017def _DidYouMeanOSMacro(bad_macro):
2018 try:
2019 return {'A': 'OS_ANDROID',
2020 'B': 'OS_BSD',
2021 'C': 'OS_CHROMEOS',
2022 'F': 'OS_FREEBSD',
2023 'L': 'OS_LINUX',
2024 'M': 'OS_MACOSX',
2025 'N': 'OS_NACL',
2026 'O': 'OS_OPENBSD',
2027 'P': 'OS_POSIX',
2028 'S': 'OS_SOLARIS',
2029 'W': 'OS_WIN'}[bad_macro[3].upper()]
2030 except KeyError:
2031 return ''
2032
2033
2034def _CheckForInvalidOSMacrosInFile(input_api, f):
2035 """Check for sensible looking, totally invalid OS macros."""
2036 preprocessor_statement = input_api.re.compile(r'^\s*#')
2037 os_macro = input_api.re.compile(r'defined\((OS_[^)]+)\)')
2038 results = []
2039 for lnum, line in f.ChangedContents():
2040 if preprocessor_statement.search(line):
2041 for match in os_macro.finditer(line):
2042 if not match.group(1) in _VALID_OS_MACROS:
2043 good = _DidYouMeanOSMacro(match.group(1))
2044 did_you_mean = ' (did you mean %s?)' % good if good else ''
2045 results.append(' %s:%d %s%s' % (f.LocalPath(),
2046 lnum,
2047 match.group(1),
2048 did_you_mean))
2049 return results
2050
2051
2052def _CheckForInvalidOSMacros(input_api, output_api):
2053 """Check all affected files for invalid OS macros."""
2054 bad_macros = []
2055 for f in input_api.AffectedFiles():
ellyjones47654342016-05-06 15:50:472056 if not f.LocalPath().endswith(('.py', '.js', '.html', '.css', '.md')):
[email protected]b00342e7f2013-03-26 16:21:542057 bad_macros.extend(_CheckForInvalidOSMacrosInFile(input_api, f))
2058
2059 if not bad_macros:
2060 return []
2061
2062 return [output_api.PresubmitError(
2063 'Possibly invalid OS macro[s] found. Please fix your code\n'
2064 'or add your macro to src/PRESUBMIT.py.', bad_macros)]
2065
lliabraa35bab3932014-10-01 12:16:442066
2067def _CheckForInvalidIfDefinedMacrosInFile(input_api, f):
2068 """Check all affected files for invalid "if defined" macros."""
2069 ALWAYS_DEFINED_MACROS = (
2070 "TARGET_CPU_PPC",
2071 "TARGET_CPU_PPC64",
2072 "TARGET_CPU_68K",
2073 "TARGET_CPU_X86",
2074 "TARGET_CPU_ARM",
2075 "TARGET_CPU_MIPS",
2076 "TARGET_CPU_SPARC",
2077 "TARGET_CPU_ALPHA",
2078 "TARGET_IPHONE_SIMULATOR",
2079 "TARGET_OS_EMBEDDED",
2080 "TARGET_OS_IPHONE",
2081 "TARGET_OS_MAC",
2082 "TARGET_OS_UNIX",
2083 "TARGET_OS_WIN32",
2084 )
2085 ifdef_macro = input_api.re.compile(r'^\s*#.*(?:ifdef\s|defined\()([^\s\)]+)')
2086 results = []
2087 for lnum, line in f.ChangedContents():
2088 for match in ifdef_macro.finditer(line):
2089 if match.group(1) in ALWAYS_DEFINED_MACROS:
2090 always_defined = ' %s is always defined. ' % match.group(1)
2091 did_you_mean = 'Did you mean \'#if %s\'?' % match.group(1)
2092 results.append(' %s:%d %s\n\t%s' % (f.LocalPath(),
2093 lnum,
2094 always_defined,
2095 did_you_mean))
2096 return results
2097
2098
2099def _CheckForInvalidIfDefinedMacros(input_api, output_api):
2100 """Check all affected files for invalid "if defined" macros."""
2101 bad_macros = []
2102 for f in input_api.AffectedFiles():
2103 if f.LocalPath().endswith(('.h', '.c', '.cc', '.m', '.mm')):
2104 bad_macros.extend(_CheckForInvalidIfDefinedMacrosInFile(input_api, f))
2105
2106 if not bad_macros:
2107 return []
2108
2109 return [output_api.PresubmitError(
2110 'Found ifdef check on always-defined macro[s]. Please fix your code\n'
2111 'or check the list of ALWAYS_DEFINED_MACROS in src/PRESUBMIT.py.',
2112 bad_macros)]
2113
2114
mlamouria82272622014-09-16 18:45:042115def _CheckForIPCRules(input_api, output_api):
2116 """Check for same IPC rules described in
2117 http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc
2118 """
2119 base_pattern = r'IPC_ENUM_TRAITS\('
2120 inclusion_pattern = input_api.re.compile(r'(%s)' % base_pattern)
2121 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_pattern)
2122
2123 problems = []
2124 for f in input_api.AffectedSourceFiles(None):
2125 local_path = f.LocalPath()
2126 if not local_path.endswith('.h'):
2127 continue
2128 for line_number, line in f.ChangedContents():
2129 if inclusion_pattern.search(line) and not comment_pattern.search(line):
2130 problems.append(
2131 '%s:%d\n %s' % (local_path, line_number, line.strip()))
2132
2133 if problems:
2134 return [output_api.PresubmitPromptWarning(
2135 _IPC_ENUM_TRAITS_DEPRECATED, problems)]
2136 else:
2137 return []
2138
[email protected]b00342e7f2013-03-26 16:21:542139
mostynbb639aca52015-01-07 20:31:232140def _CheckForWindowsLineEndings(input_api, output_api):
2141 """Check source code and known ascii text files for Windows style line
2142 endings.
2143 """
earthdok1b5e0ee2015-03-10 15:19:102144 known_text_files = r'.*\.(txt|html|htm|mhtml|py|gyp|gypi|gn|isolate)$'
mostynbb639aca52015-01-07 20:31:232145
2146 file_inclusion_pattern = (
2147 known_text_files,
2148 r'.+%s' % _IMPLEMENTATION_EXTENSIONS
2149 )
2150
2151 filter = lambda f: input_api.FilterSourceFile(
2152 f, white_list=file_inclusion_pattern, black_list=None)
2153 files = [f.LocalPath() for f in
2154 input_api.AffectedSourceFiles(filter)]
2155
2156 problems = []
2157
2158 for file in files:
2159 fp = open(file, 'r')
2160 for line in fp:
2161 if line.endswith('\r\n'):
2162 problems.append(file)
2163 break
2164 fp.close()
2165
2166 if problems:
2167 return [output_api.PresubmitPromptWarning('Are you sure that you want '
2168 'these files to contain Windows style line endings?\n' +
2169 '\n'.join(problems))]
2170
2171 return []
2172
2173
[email protected]1f7b4172010-01-28 01:17:342174def CheckChangeOnUpload(input_api, output_api):
2175 results = []
2176 results.extend(_CommonChecks(input_api, output_api))
tandriief664692014-09-23 14:51:472177 results.extend(_CheckValidHostsInDEPS(input_api, output_api))
scottmg39b29952014-12-08 18:31:282178 results.extend(
2179 input_api.canned_checks.CheckGNFormatted(input_api, output_api))
mcasasb7440c282015-02-04 14:52:192180 results.extend(_CheckUmaHistogramChanges(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:222181 results.extend(_AndroidSpecificOnUploadChecks(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542182 return results
[email protected]ca8d19842009-02-19 16:33:122183
2184
[email protected]1bfb8322014-04-23 01:02:412185def GetTryServerMasterForBot(bot):
2186 """Returns the Try Server master for the given bot.
2187
[email protected]0bb112362014-07-26 04:38:322188 It tries to guess the master from the bot name, but may still fail
2189 and return None. There is no longer a default master.
2190 """
2191 # Potentially ambiguous bot names are listed explicitly.
2192 master_map = {
[email protected]0bb112362014-07-26 04:38:322193 'chromium_presubmit': 'tryserver.chromium.linux',
[email protected]0bb112362014-07-26 04:38:322194 'tools_build_presubmit': 'tryserver.chromium.linux',
[email protected]1bfb8322014-04-23 01:02:412195 }
[email protected]0bb112362014-07-26 04:38:322196 master = master_map.get(bot)
2197 if not master:
wnwen4fbaab82016-05-25 12:54:362198 if 'android' in bot:
2199 master = 'tryserver.chromium.android'
2200 elif 'linux' in bot or 'presubmit' in bot:
[email protected]0bb112362014-07-26 04:38:322201 master = 'tryserver.chromium.linux'
2202 elif 'win' in bot:
2203 master = 'tryserver.chromium.win'
2204 elif 'mac' in bot or 'ios' in bot:
2205 master = 'tryserver.chromium.mac'
2206 return master
[email protected]1bfb8322014-04-23 01:02:412207
2208
Paweł Hajdan, Jr55083782014-12-19 20:32:562209def GetDefaultTryConfigs(bots):
2210 """Returns a list of ('bot', set(['tests']), filtered by [bots].
[email protected]38c6a512013-12-18 23:48:012211 """
2212
Paweł Hajdan, Jr55083782014-12-19 20:32:562213 builders_and_tests = dict((bot, set(['defaulttests'])) for bot in bots)
[email protected]1bfb8322014-04-23 01:02:412214
2215 # Build up the mapping from tryserver master to bot/test.
2216 out = dict()
Paweł Hajdan, Jr55083782014-12-19 20:32:562217 for bot, tests in builders_and_tests.iteritems():
[email protected]1bfb8322014-04-23 01:02:412218 out.setdefault(GetTryServerMasterForBot(bot), {})[bot] = tests
2219 return out
[email protected]38c6a512013-12-18 23:48:012220
2221
[email protected]ca8d19842009-02-19 16:33:122222def CheckChangeOnCommit(input_api, output_api):
[email protected]fe5f57c52009-06-05 14:25:542223 results = []
[email protected]1f7b4172010-01-28 01:17:342224 results.extend(_CommonChecks(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542225 # Make sure the tree is 'open'.
[email protected]806e98e2010-03-19 17:49:272226 results.extend(input_api.canned_checks.CheckTreeIsOpen(
[email protected]7f238152009-08-12 19:00:342227 input_api,
2228 output_api,
[email protected]2fdd1f362013-01-16 03:56:032229 json_url='http://chromium-status.appspot.com/current?format=json'))
[email protected]806e98e2010-03-19 17:49:272230
[email protected]3e4eb112011-01-18 03:29:542231 results.extend(input_api.canned_checks.CheckChangeHasBugField(
2232 input_api, output_api))
[email protected]c4b47562011-12-05 23:39:412233 results.extend(input_api.canned_checks.CheckChangeHasDescription(
2234 input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542235 return results