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

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: alphabetize imports 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.
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
15 import os.path
12 import re 16 import re
M-A Ruel 2012/02/06 20:29:27 This import was an oversight in http://codereview.
Tyler Breisacher (Chromium) 2012/02/06 22:00:13 Done. This means I have to move ErrorHandlerImpl i
M-A Ruel 2012/02/07 00:34:09 no. :)
13 17
14
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
M-A Ruel 2012/02/06 20:29:27 2 vertical lines between file level symbols please
Tyler Breisacher (Chromium) 2012/02/06 22:00:13 Done.
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 = []
M-A Ruel 2012/02/06 20:29:27 if you used self.errors = [], then you wouldn't ne
Tyler Breisacher (Chromium) 2012/02/06 22:00:13 I think the JavaScriptStyleChecker only calls Hand
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
M-A Ruel 2012/02/06 20:29:27 What's list.empty?
Tyler Breisacher (Chromium) 2012/02/06 22:00:13 *facepalm*. Thank you! Done.
56
57 def _valid(self, error):
58 '''Check whether an error is valid. Most errors are valid, with a few
M-A Ruel 2012/02/06 20:29:27 All the rest of the file use """for docstrings""".
Tyler Breisacher (Chromium) 2012/02/06 22:00:13 Done.
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())
M-A Ruel 2012/02/06 20:29:27 input_api.re
Tyler Breisacher (Chromium) 2012/02/06 22:00:13 Done.
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()):
Tyler Breisacher (Chromium) 2012/02/06 22:00:13 Off by one error! The first line is line 1, not li
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 const_re = re.compile(r'\bconst\b')
101 if const_re.search(line):
102 errorLines.append(' line %d: %s\n%s' % (
103 i,
104 'Use |var| instead of |const|. See http://crbug.com/80149',
105 line))
106
107 # Use closure_linter to check for several different errors
108 error_handler = ErrorHandlerImpl()
109 checker = closure_linter.checker.JavaScriptStyleChecker(error_handler)
110 checker.Check(f.LocalPath())
111
112 for error in error_handler.GetErrors():
113 errorMsg = ' line %d: E%04d: %s\n%s' % (
114 error.token.line_number,
115 error.code,
116 error.message,
117 error.token.line)
118 errorLines.append(errorMsg)
119
120 if errorLines:
121 errorLines = [
122 'Found JavaScript style violations in %s:' %
123 f.LocalPath()] + errorLines
124 results.append(output_api.PresubmitError('\n'.join(errorLines)))
125
126 if results:
127 results.append(output_api.PresubmitNotifyResult(
128 'See the JavaScript style guide at '
129 'http://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml'
130 ' and contact tbreisacher@chromium.org for feedback on this'
131 ' PRESUBMIT check.'))
132
133 return results
33 134
34 def _CheckNoInterfacesInBase(input_api, output_api): 135 def _CheckNoInterfacesInBase(input_api, output_api):
35 """Checks to make sure no files in libbase.a have |@interface|.""" 136 """Checks to make sure no files in libbase.a have |@interface|."""
36 pattern = input_api.re.compile(r'^\s*@interface', input_api.re.MULTILINE) 137 pattern = input_api.re.compile(r'^\s*@interface', input_api.re.MULTILINE)
37 files = [] 138 files = []
38 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile): 139 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
39 if (f.LocalPath().startswith('base/') and 140 if (f.LocalPath().startswith('base/') and
40 not f.LocalPath().endswith('_unittest.mm')): 141 not f.LocalPath().endswith('_unittest.mm')):
41 contents = input_api.ReadFile(f) 142 contents = input_api.ReadFile(f)
42 if pattern.search(contents): 143 if pattern.search(contents):
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after
207 if not problems: 308 if not problems:
208 return [] 309 return []
209 return [output_api.PresubmitPromptWarning('The old callback system is ' 310 return [output_api.PresubmitPromptWarning('The old callback system is '
210 'deprecated. If possible, use base::Bind and base::Callback instead.\n' + 311 'deprecated. If possible, use base::Bind and base::Callback instead.\n' +
211 '\n'.join(problems))] 312 '\n'.join(problems))]
212 313
213 314
214 def _CommonChecks(input_api, output_api): 315 def _CommonChecks(input_api, output_api):
215 """Checks common to both upload and commit.""" 316 """Checks common to both upload and commit."""
216 results = [] 317 results = []
318 results.extend(_CheckJavaScriptStyle(input_api, output_api))
217 results.extend(input_api.canned_checks.PanProjectChecks( 319 results.extend(input_api.canned_checks.PanProjectChecks(
218 input_api, output_api, excluded_paths=_EXCLUDED_PATHS)) 320 input_api, output_api, excluded_paths=_EXCLUDED_PATHS))
219 results.extend(_CheckNoInterfacesInBase(input_api, output_api)) 321 results.extend(_CheckNoInterfacesInBase(input_api, output_api))
220 results.extend(_CheckAuthorizedAuthor(input_api, output_api)) 322 results.extend(_CheckAuthorizedAuthor(input_api, output_api))
221 results.extend( 323 results.extend(
222 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api)) 324 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api))
223 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api)) 325 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
224 results.extend(_CheckNoNewWStrings(input_api, output_api)) 326 results.extend(_CheckNoNewWStrings(input_api, output_api))
225 results.extend(_CheckNoDEPSGIT(input_api, output_api)) 327 results.extend(_CheckNoDEPSGIT(input_api, output_api))
226 results.extend(_CheckNoFRIEND_TEST(input_api, output_api)) 328 results.extend(_CheckNoFRIEND_TEST(input_api, output_api))
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
336 def GetPreferredTrySlaves(project, change): 438 def GetPreferredTrySlaves(project, change):
337 only_objc_files = all( 439 only_objc_files = all(
338 f.LocalPath().endswith(('.mm', '.m')) for f in change.AffectedFiles()) 440 f.LocalPath().endswith(('.mm', '.m')) for f in change.AffectedFiles())
339 if only_objc_files: 441 if only_objc_files:
340 return ['mac_rel'] 442 return ['mac_rel']
341 preferred = ['win_rel', 'linux_rel', 'mac_rel'] 443 preferred = ['win_rel', 'linux_rel', 'mac_rel']
342 aura_re = '_aura[^/]*[.][^/]*' 444 aura_re = '_aura[^/]*[.][^/]*'
343 if any(re.search(aura_re, f.LocalPath()) for f in change.AffectedFiles()): 445 if any(re.search(aura_re, f.LocalPath()) for f in change.AffectedFiles()):
344 preferred.append('linux_chromeos') 446 preferred.append('linux_chromeos')
345 return preferred 447 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