Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(902)

Side by Side Diff: PRESUBMIT.py

Issue 9288045: PRESUBMIT check for JavaScript style errors (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: nits Created 8 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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.
Dan Beam 2012/02/07 09:08:00 This check should probably not be in src/PRESUBMIT
Tyler Breisacher (Chromium) 2012/02/08 02:49:28 Done.
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
12 import re
13
14
15 _EXCLUDED_PATHS = ( 11 _EXCLUDED_PATHS = (
16 r"^breakpad[\\\/].*", 12 r"^breakpad[\\\/].*",
17 r"^native_client_sdk[\\\/].*", 13 r"^native_client_sdk[\\\/].*",
18 r"^net[\\\/]tools[\\\/]spdyshark[\\\/].*", 14 r"^net[\\\/]tools[\\\/]spdyshark[\\\/].*",
19 r"^skia[\\\/].*", 15 r"^skia[\\\/].*",
20 r"^v8[\\\/].*", 16 r"^v8[\\\/].*",
21 r".*MakeFile$", 17 r".*MakeFile$",
22 ) 18 )
23 19
24 20
25 _TEST_ONLY_WARNING = ( 21 _TEST_ONLY_WARNING = (
26 'You might be calling functions intended only for testing from\n' 22 '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' 23 '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' 24 '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' 25 'not perfect. The commit queue will not block on this warning.\n'
30 'Email joi@chromium.org if you have questions.') 26 'Email joi@chromium.org if you have questions.')
31 27
32 28
29 def _CheckJavaScriptStyle(input_api, output_api):
30 """Check for JavaScript style violations."""
Dan Beam 2012/02/07 09:08:00 Mention that this is checking against our web deve
Tyler Breisacher (Chromium) 2012/02/08 02:49:28 Done.
31
32 import closure_linter.common.errorhandler
Dan Beam 2012/02/07 09:08:00 Are these actually local imports or is it the same
M-A Ruel 2012/02/07 14:16:04 That's a local import, it's fine.
33
34 class ErrorHandlerImpl(closure_linter.common.errorhandler.ErrorHandler):
35 """Implementation of ErrorHandler that collects all errors except those
36 that don't apply for Chromium JavaScript code.
37 """
38
39 def __init__(self):
40 self._errors = []
41
42 def HandleFile(self, filename, first_token):
43 self._filename = filename
44
45 def HandleError(self, error):
46 if (self._valid(error)):
47 error.filename = self._filename
48 self._errors.append(error)
49
50 def GetErrors(self):
51 return self._errors
52
53 def HasErrors(self):
54 return bool(self._errors)
55
56 def _valid(self, error):
57 """Check whether an error is valid. Most errors are valid, with a few
58 exceptions which are listed here.
59 """
60
61 import closure_linter.errors
62
63 return error.code not in [
64 closure_linter.errors.COMMA_AT_END_OF_LITERAL,
65 closure_linter.errors.JSDOC_ILLEGAL_QUESTION_WITH_PIPE,
66 closure_linter.errors.
67 JSDOC_TAG_DESCRIPTION_ENDS_WITH_INVALID_CHARACTER,
68 ]
69
70 import closure_linter.checker
71
72 # Only check the following folders. OWNERS of folders containing JavaScript
73 # code can opt-in to this check by adding the folder here.
74 join = input_api.os_path.join
75 checked_folders = [
76 join('chrome', 'browser', 'resources', 'ntp4'),
77 join('chrome', 'browser', 'resources', 'options2'),
78 ]
79
80 def inCheckedFolder(affected_file):
Dan Beam 2012/02/07 09:08:00 I thought we used in_checked_folder for local func
M-A Ruel 2012/02/07 14:16:04 Right.
Tyler Breisacher (Chromium) 2012/02/08 02:49:28 Done.
81 return any(affected_file.LocalPath().startswith(cf)
Dan Beam 2012/02/07 09:08:00 Is this safe to assume? What if I have a CL that
Tyler Breisacher (Chromium) 2012/02/08 02:49:28 Good point, I'm not sure what we can do about it e
82 for cf in checked_folders)
83
84 def jsOrHtml(affected_file):
85 return input_api.re.search('\.(js|html?)$', affected_file.LocalPath())
Dan Beam 2012/02/07 09:08:00 Why are you checking HTML?
Tyler Breisacher (Chromium) 2012/02/08 02:49:28 It's already equipped to check JS code in <script>
86
87 def fileFilter(affected_file):
88 return jsOrHtml(affected_file) and inCheckedFolder(affected_file)
89
90 results = []
91
92 for f in input_api.change.AffectedFiles(file_filter=fileFilter):
93 errorLines = []
Dan Beam 2012/02/07 09:08:00 camelCase in JS, under_scores in Python and C++ fo
Tyler Breisacher (Chromium) 2012/02/08 02:49:28 Done.
94
95 # check for getElementById()
96 for i, line in enumerate(f.NewContents(), start=1):
Dan Beam 2012/02/07 09:08:00 Whay are you starting at 1?
M-A Ruel 2012/02/07 14:16:04 Because line numbers starting at 0 are unintuitive
Tyler Breisacher (Chromium) 2012/02/08 02:49:28 Neither way is particularly more intuitive than th
97 if 'getElementById' in line:
Dan Beam 2012/02/07 09:08:00 nit: I think this should be slightly more robust,
Tyler Breisacher (Chromium) 2012/02/08 02:49:28 I think this is probably okay as is, to be honest.
98 errorLines.append(' line %d: %s\n%s' % (
99 i,
100 'Use $() instead of document.getElementById()',
Dan Beam 2012/02/07 09:08:00 nit: $('id') to show we're not using jQuery (thoug
Tyler Breisacher (Chromium) 2012/02/08 02:49:28 Done.
101 line))
102
103 if input_api.re.search(r'\bconst\b', line):
Dan Beam 2012/02/07 09:08:00 Doesn't closure have something for this?
Tyler Breisacher (Chromium) 2012/02/08 02:49:28 You would think so, but no :(
104 errorLines.append(' line %d: %s\n%s' % (
105 i,
106 'Use |var| instead of |const|. See http://crbug.com/80149',
107 line))
108
109 # Use closure_linter to check for several different errors
110 error_handler = ErrorHandlerImpl()
111 checker = closure_linter.checker.JavaScriptStyleChecker(error_handler)
112 checker.Check(f.LocalPath())
113
114 for error in error_handler.GetErrors():
115 errorMsg = ' line %d: E%04d: %s\n%s' % (
116 error.token.line_number,
117 error.code,
Dan Beam 2012/02/07 09:08:00 Do you think the average user will care about this
Tyler Breisacher (Chromium) 2012/02/08 02:49:28 Generally, no, but if this check complains about s
118 error.message,
119 error.token.line)
120 errorLines.append(errorMsg)
121
122 if errorLines:
123 errorLines = [
124 'Found JavaScript style violations in %s:' %
125 f.LocalPath()] + errorLines
126 results.append(output_api.PresubmitError('\n'.join(errorLines)))
127
128 if results:
129 results.append(output_api.PresubmitNotifyResult(
130 'See the JavaScript style guide at '
131 'http://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml'
Dan Beam 2012/02/07 09:08:00 This is not necessarily the guide we're following.
Tyler Breisacher (Chromium) 2012/02/08 02:49:28 Done.
132 ' and contact tbreisacher@chromium.org for feedback on this'
Dan Beam 2012/02/07 09:08:00 nit: This sounds like they're contacting you for f
Tyler Breisacher (Chromium) 2012/02/08 02:49:28 Done.
133 ' PRESUBMIT check.'))
134
135 return results
136
33 137
34 def _CheckNoInterfacesInBase(input_api, output_api): 138 def _CheckNoInterfacesInBase(input_api, output_api):
35 """Checks to make sure no files in libbase.a have |@interface|.""" 139 """Checks to make sure no files in libbase.a have |@interface|."""
36 pattern = input_api.re.compile(r'^\s*@interface', input_api.re.MULTILINE) 140 pattern = input_api.re.compile(r'^\s*@interface', input_api.re.MULTILINE)
37 files = [] 141 files = []
38 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile): 142 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
39 if (f.LocalPath().startswith('base/') and 143 if (f.LocalPath().startswith('base/') and
40 not f.LocalPath().endswith('_unittest.mm')): 144 not f.LocalPath().endswith('_unittest.mm')):
41 contents = input_api.ReadFile(f) 145 contents = input_api.ReadFile(f)
42 if pattern.search(contents): 146 if pattern.search(contents):
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after
207 if not problems: 311 if not problems:
208 return [] 312 return []
209 return [output_api.PresubmitPromptWarning('The old callback system is ' 313 return [output_api.PresubmitPromptWarning('The old callback system is '
210 'deprecated. If possible, use base::Bind and base::Callback instead.\n' + 314 'deprecated. If possible, use base::Bind and base::Callback instead.\n' +
211 '\n'.join(problems))] 315 '\n'.join(problems))]
212 316
213 317
214 def _CommonChecks(input_api, output_api): 318 def _CommonChecks(input_api, output_api):
215 """Checks common to both upload and commit.""" 319 """Checks common to both upload and commit."""
216 results = [] 320 results = []
321 results.extend(_CheckJavaScriptStyle(input_api, output_api))
217 results.extend(input_api.canned_checks.PanProjectChecks( 322 results.extend(input_api.canned_checks.PanProjectChecks(
218 input_api, output_api, excluded_paths=_EXCLUDED_PATHS)) 323 input_api, output_api, excluded_paths=_EXCLUDED_PATHS))
219 results.extend(_CheckNoInterfacesInBase(input_api, output_api)) 324 results.extend(_CheckNoInterfacesInBase(input_api, output_api))
220 results.extend(_CheckAuthorizedAuthor(input_api, output_api)) 325 results.extend(_CheckAuthorizedAuthor(input_api, output_api))
221 results.extend( 326 results.extend(
222 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api)) 327 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api))
223 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api)) 328 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
224 results.extend(_CheckNoNewWStrings(input_api, output_api)) 329 results.extend(_CheckNoNewWStrings(input_api, output_api))
225 results.extend(_CheckNoDEPSGIT(input_api, output_api)) 330 results.extend(_CheckNoDEPSGIT(input_api, output_api))
226 results.extend(_CheckNoFRIEND_TEST(input_api, output_api)) 331 results.extend(_CheckNoFRIEND_TEST(input_api, output_api))
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
333 return results 438 return results
334 439
335 440
336 def GetPreferredTrySlaves(project, change): 441 def GetPreferredTrySlaves(project, change):
337 only_objc_files = all( 442 only_objc_files = all(
338 f.LocalPath().endswith(('.mm', '.m')) for f in change.AffectedFiles()) 443 f.LocalPath().endswith(('.mm', '.m')) for f in change.AffectedFiles())
339 if only_objc_files: 444 if only_objc_files:
340 return ['mac_rel'] 445 return ['mac_rel']
341 preferred = ['win_rel', 'linux_rel', 'mac_rel'] 446 preferred = ['win_rel', 'linux_rel', 'mac_rel']
342 aura_re = '_aura[^/]*[.][^/]*' 447 aura_re = '_aura[^/]*[.][^/]*'
343 if any(re.search(aura_re, f.LocalPath()) for f in change.AffectedFiles()): 448 if any(input_api.re.search(aura_re, f.LocalPath())
Dan Beam 2012/02/07 09:08:00 Where exactly are you getting this input_api varia
M-A Ruel 2012/02/07 14:16:04 It's not Tyler's fault. Imports are slow in python
449 for f in change.AffectedFiles()):
344 preferred.append('linux_chromeos') 450 preferred.append('linux_chromeos')
345 return preferred 451 return preferred
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698