Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 """Top-level presubmit script for Chromium. | 5 """Top-level presubmit script for Chromium. |
| 6 | 6 |
| 7 See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts | 7 See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts |
| 8 for more details about the presubmit API built into gcl. | 8 for more details about the presubmit API built into gcl. |
| 9 """ | 9 """ |
| 10 | 10 |
| 11 | 11 |
| 12 import closure_linter.checker | |
| 13 import closure_linter.common.errorhandler | |
| 14 import closure_linter.errors | |
| 12 import re | 15 import re |
| 13 | 16 import os.path |
| 14 | 17 |
| 15 _EXCLUDED_PATHS = ( | 18 _EXCLUDED_PATHS = ( |
| 16 r"^breakpad[\\\/].*", | 19 r"^breakpad[\\\/].*", |
| 17 r"^native_client_sdk[\\\/].*", | 20 r"^native_client_sdk[\\\/].*", |
| 18 r"^net[\\\/]tools[\\\/]spdyshark[\\\/].*", | 21 r"^net[\\\/]tools[\\\/]spdyshark[\\\/].*", |
| 19 r"^skia[\\\/].*", | 22 r"^skia[\\\/].*", |
| 20 r"^v8[\\\/].*", | 23 r"^v8[\\\/].*", |
| 21 r".*MakeFile$", | 24 r".*MakeFile$", |
| 22 ) | 25 ) |
| 23 | 26 |
| 24 | 27 |
| 25 _TEST_ONLY_WARNING = ( | 28 _TEST_ONLY_WARNING = ( |
| 26 'You might be calling functions intended only for testing from\n' | 29 'You might be calling functions intended only for testing from\n' |
| 27 'production code. It is OK to ignore this warning if you know what\n' | 30 'production code. It is OK to ignore this warning if you know what\n' |
| 28 'you are doing, as the heuristics used to detect the situation are\n' | 31 'you are doing, as the heuristics used to detect the situation are\n' |
| 29 'not perfect. The commit queue will not block on this warning.\n' | 32 'not perfect. The commit queue will not block on this warning.\n' |
| 30 'Email joi@chromium.org if you have questions.') | 33 'Email joi@chromium.org if you have questions.') |
| 31 | 34 |
| 35 class ErrorHandlerImpl(closure_linter.common.errorhandler.ErrorHandler): | |
| 36 '''Implementation of ErrorHandler that collects all errors except those | |
| 37 that don't apply for Chromium JavaScript code. | |
| 38 ''' | |
| 32 | 39 |
| 40 def __init__(self): | |
| 41 self._errors = [] | |
| 42 | |
| 43 def HandleFile(self, filename, first_token): | |
| 44 self._filename = filename | |
| 45 | |
| 46 def HandleError(self, error): | |
| 47 if (self._valid(error)): | |
| 48 error.filename = self._filename | |
| 49 self._errors.append(error) | |
| 50 | |
| 51 def GetErrors(self): | |
| 52 return self._errors | |
| 53 | |
| 54 def HasErrors(self): | |
| 55 return not self._errors.empty | |
| 56 | |
| 57 def _valid(self, error): | |
| 58 '''Check whether an error is valid. Most errors are valid, with a few | |
| 59 exceptions which are listed here. | |
| 60 ''' | |
| 61 return error.code not in [ | |
| 62 closure_linter.errors.COMMA_AT_END_OF_LITERAL, | |
| 63 closure_linter.errors.JSDOC_ILLEGAL_QUESTION_WITH_PIPE, | |
| 64 closure_linter.errors.JSDOC_TAG_DESCRIPTION_ENDS_WITH_INVALID_CHARACTER | |
| 65 ] | |
| 66 | |
| 67 def _CheckJavaScriptStyle(input_api, output_api): | |
| 68 """Check for JavaScript style violations.""" | |
| 69 | |
| 70 # Only check the following folders. OWNERS of folders containing JavaScript | |
| 71 # code can opt-in to this check by adding the folder here. | |
| 72 checked_folders = [ | |
| 73 os.path.join('chrome', 'browser', 'resources', 'ntp4'), | |
| 74 os.path.join('chrome', 'browser', 'resources', 'options2'), | |
| 75 ] | |
| 76 | |
| 77 def inCheckedFolder(affected_file): | |
| 78 return any(affected_file.LocalPath().startswith(cf) | |
| 79 for cf in checked_folders) | |
| 80 | |
| 81 def jsOrHtml(affected_file): | |
| 82 return re.search('\.(js|html?)$', affected_file.LocalPath()) | |
| 83 | |
| 84 def fileFilter(affected_file): | |
| 85 return jsOrHtml(affected_file) and inCheckedFolder(affected_file) | |
| 86 | |
| 87 results = [] | |
| 88 | |
| 89 for f in input_api.change.AffectedFiles(file_filter=fileFilter): | |
| 90 errorLines = [] | |
| 91 | |
| 92 # check for getElementById() | |
| 93 for i, line in enumerate(f.NewContents()): | |
| 94 if 'getElementById' in line: | |
| 95 errorLines.append(' line %d: %s\n%s' % ( | |
| 96 i, | |
| 97 'Use $() instead of document.getElementById()', | |
| 98 line)) | |
| 99 | |
| 100 # Use closure_linter to check for several different errors | |
| 101 error_handler = ErrorHandlerImpl() | |
| 102 checker = closure_linter.checker.JavaScriptStyleChecker(error_handler) | |
| 103 checker.Check(f.LocalPath()) | |
| 104 | |
| 105 for error in error_handler.GetErrors(): | |
| 106 errorMsg = ' line %d: E%04d: %s\n%s' % ( | |
| 107 error.token.line_number, | |
| 108 error.code, | |
| 109 error.message, | |
| 110 error.token.line) | |
| 111 errorLines.append(errorMsg) | |
| 112 | |
| 113 if errorLines: | |
| 114 errorLines = [ | |
| 115 'Found JavaScript style violations in %s:' % | |
| 116 f.LocalPath()] + errorLines | |
| 117 results.append(output_api.PresubmitError('\n'.join(errorLines))) | |
| 118 | |
| 119 if results: | |
| 120 results.append(output_api.PresubmitNotifyResult( | |
| 121 'See the JavaScript style guide at ' | |
| 122 'http://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml' | |
| 123 ' and contact tbreisacher@chromium.org for feedback on this' | |
| 124 ' PRESUBMIT check.')) | |
| 125 | |
| 126 return results | |
| 33 | 127 |
| 34 def _CheckNoInterfacesInBase(input_api, output_api): | 128 def _CheckNoInterfacesInBase(input_api, output_api): |
| 35 """Checks to make sure no files in libbase.a have |@interface|.""" | 129 """Checks to make sure no files in libbase.a have |@interface|.""" |
| 36 pattern = input_api.re.compile(r'^\s*@interface', input_api.re.MULTILINE) | 130 pattern = input_api.re.compile(r'^\s*@interface', input_api.re.MULTILINE) |
| 37 files = [] | 131 files = [] |
| 38 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile): | 132 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile): |
| 39 if (f.LocalPath().startswith('base/') and | 133 if (f.LocalPath().startswith('base/') and |
| 40 not f.LocalPath().endswith('_unittest.mm')): | 134 not f.LocalPath().endswith('_unittest.mm')): |
| 41 contents = input_api.ReadFile(f) | 135 contents = input_api.ReadFile(f) |
| 42 if pattern.search(contents): | 136 if pattern.search(contents): |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 207 if not problems: | 301 if not problems: |
| 208 return [] | 302 return [] |
| 209 return [output_api.PresubmitPromptWarning('The old callback system is ' | 303 return [output_api.PresubmitPromptWarning('The old callback system is ' |
| 210 'deprecated. If possible, use base::Bind and base::Callback instead.\n' + | 304 'deprecated. If possible, use base::Bind and base::Callback instead.\n' + |
| 211 '\n'.join(problems))] | 305 '\n'.join(problems))] |
| 212 | 306 |
| 213 | 307 |
| 214 def _CommonChecks(input_api, output_api): | 308 def _CommonChecks(input_api, output_api): |
| 215 """Checks common to both upload and commit.""" | 309 """Checks common to both upload and commit.""" |
| 216 results = [] | 310 results = [] |
| 311 results.extend(_CheckJavaScriptStyle(input_api, output_api)) | |
|
Dan Beam
2012/02/03 03:09:13
Damn, I guess I should be doing my checks in this
| |
| 217 results.extend(input_api.canned_checks.PanProjectChecks( | 312 results.extend(input_api.canned_checks.PanProjectChecks( |
| 218 input_api, output_api, excluded_paths=_EXCLUDED_PATHS)) | 313 input_api, output_api, excluded_paths=_EXCLUDED_PATHS)) |
| 219 results.extend(_CheckNoInterfacesInBase(input_api, output_api)) | 314 results.extend(_CheckNoInterfacesInBase(input_api, output_api)) |
| 220 results.extend(_CheckAuthorizedAuthor(input_api, output_api)) | 315 results.extend(_CheckAuthorizedAuthor(input_api, output_api)) |
| 221 results.extend( | 316 results.extend( |
| 222 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api)) | 317 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api)) |
| 223 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api)) | 318 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api)) |
| 224 results.extend(_CheckNoNewWStrings(input_api, output_api)) | 319 results.extend(_CheckNoNewWStrings(input_api, output_api)) |
| 225 results.extend(_CheckNoDEPSGIT(input_api, output_api)) | 320 results.extend(_CheckNoDEPSGIT(input_api, output_api)) |
| 226 results.extend(_CheckNoFRIEND_TEST(input_api, output_api)) | 321 results.extend(_CheckNoFRIEND_TEST(input_api, output_api)) |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 336 def GetPreferredTrySlaves(project, change): | 431 def GetPreferredTrySlaves(project, change): |
| 337 only_objc_files = all( | 432 only_objc_files = all( |
| 338 f.LocalPath().endswith(('.mm', '.m')) for f in change.AffectedFiles()) | 433 f.LocalPath().endswith(('.mm', '.m')) for f in change.AffectedFiles()) |
| 339 if only_objc_files: | 434 if only_objc_files: |
| 340 return ['mac_rel'] | 435 return ['mac_rel'] |
| 341 preferred = ['win_rel', 'linux_rel', 'mac_rel'] | 436 preferred = ['win_rel', 'linux_rel', 'mac_rel'] |
| 342 aura_re = '_aura[^/]*[.][^/]*' | 437 aura_re = '_aura[^/]*[.][^/]*' |
| 343 if any(re.search(aura_re, f.LocalPath()) for f in change.AffectedFiles()): | 438 if any(re.search(aura_re, f.LocalPath()) for f in change.AffectedFiles()): |
| 344 preferred.append('linux_chromeos_aura:compile') | 439 preferred.append('linux_chromeos_aura:compile') |
| 345 return preferred | 440 return preferred |
| OLD | NEW |