| OLD | NEW |
| (Empty) |
| 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 | |
| 3 # found in the LICENSE file. | |
| 4 | |
| 5 """Presubmit script for Chromium JS resources. | |
| 6 | |
| 7 See chrome/browser/PRESUBMIT.py | |
| 8 """ | |
| 9 | |
| 10 import regex_check | |
| 11 | |
| 12 | |
| 13 class JSChecker(object): | |
| 14 def __init__(self, input_api, output_api, file_filter=None): | |
| 15 self.input_api = input_api | |
| 16 self.output_api = output_api | |
| 17 self.file_filter = file_filter | |
| 18 | |
| 19 def RegexCheck(self, line_number, line, regex, message): | |
| 20 return regex_check.RegexCheck( | |
| 21 self.input_api.re, line_number, line, regex, message) | |
| 22 | |
| 23 def ChromeSendCheck(self, i, line): | |
| 24 """Checks for a particular misuse of 'chrome.send'.""" | |
| 25 return self.RegexCheck(i, line, r"chrome\.send\('[^']+'\s*(, \[\])\)", | |
| 26 'Passing an empty array to chrome.send is unnecessary') | |
| 27 | |
| 28 def CommentIfAndIncludeCheck(self, line_number, line): | |
| 29 return self.RegexCheck(line_number, line, r'(?<!\/\/ )(<if|<include) ', | |
| 30 '<if> or <include> should be in a single line comment with a space ' + | |
| 31 'after the slashes. Examples:\n' + | |
| 32 ' // <include src="...">\n' + | |
| 33 ' // <if expr="chromeos">\n' + | |
| 34 ' // </if>\n') | |
| 35 | |
| 36 def ConstCheck(self, i, line): | |
| 37 """Check for use of the 'const' keyword.""" | |
| 38 if self.input_api.re.search(r'\*\s+@const', line): | |
| 39 # Probably a JsDoc line | |
| 40 return '' | |
| 41 | |
| 42 return self.RegexCheck(i, line, r'(?:^|\s|\()(const)\s', | |
| 43 'Use /** @const */ var varName; instead of const varName;') | |
| 44 | |
| 45 def EndJsDocCommentCheck(self, i, line): | |
| 46 msg = 'End JSDoc comments with */ instead of **/' | |
| 47 def _check(regex): | |
| 48 return self.RegexCheck(i, line, regex, msg) | |
| 49 return _check(r'^\s*(\*\*/)\s*$') or _check(r'/\*\* @[a-zA-Z]+.* (\*\*/)') | |
| 50 | |
| 51 def ExtraDotInGenericCheck(self, i, line): | |
| 52 return self.RegexCheck(i, line, r"((?:Array|Object|Promise)\.<)", | |
| 53 "Don't use a dot after generics (Object.<T> should be Object<T>).") | |
| 54 | |
| 55 def GetElementByIdCheck(self, i, line): | |
| 56 """Checks for use of 'document.getElementById' instead of '$'.""" | |
| 57 return self.RegexCheck(i, line, r"(document\.getElementById)\('", | |
| 58 "Use $('id') or getSVGElement('id') from chrome://resources/js/util.js " | |
| 59 "instead of document.getElementById('id')") | |
| 60 | |
| 61 def InheritDocCheck(self, i, line): | |
| 62 """Checks for use of '@inheritDoc' instead of '@override'.""" | |
| 63 return self.RegexCheck(i, line, r"\* (@inheritDoc)", | |
| 64 "@inheritDoc is deprecated, use @override instead") | |
| 65 | |
| 66 def PolymerLocalIdCheck(self, i, line): | |
| 67 """Checks for use of element.$.localId.""" | |
| 68 return self.RegexCheck(i, line, r"(?<!this)(\.\$)[\[\.]", | |
| 69 "Please only use this.$.localId, not element.$.localId") | |
| 70 | |
| 71 def WrapperTypeCheck(self, i, line): | |
| 72 """Check for wrappers (new String()) instead of builtins (string).""" | |
| 73 return self.RegexCheck(i, line, | |
| 74 r"(?:/\*)?\*.*?@(?:param|return|type) ?" # /** @param/@return/@type | |
| 75 r"{[^}]*\b(String|Boolean|Number)\b[^}]*}", # {(Boolean|Number|String)} | |
| 76 "Don't use wrapper types (i.e. new String() or @type {String})") | |
| 77 | |
| 78 def VarNameCheck(self, i, line): | |
| 79 """See the style guide. http://goo.gl/eQiXVW""" | |
| 80 return self.RegexCheck(i, line, | |
| 81 r"var (?!g_\w+)(_?[a-z][a-zA-Z]*[_$][\w_$]*)(?<! \$)", | |
| 82 "Please use var namesLikeThis <https://goo.gl/eQiXVW>") | |
| 83 | |
| 84 def _GetErrorHighlight(self, start, length): | |
| 85 """Takes a start position and a length, and produces a row of '^'s to | |
| 86 highlight the corresponding part of a string. | |
| 87 """ | |
| 88 return start * ' ' + length * '^' | |
| 89 | |
| 90 def RunChecks(self): | |
| 91 """Check for violations of the Chromium JavaScript style guide. See | |
| 92 https://chromium.googlesource.com/chromium/src/+/master/styleguide/web/we
b.md#JavaScript | |
| 93 """ | |
| 94 results = [] | |
| 95 | |
| 96 affected_files = self.input_api.change.AffectedFiles( | |
| 97 file_filter=self.file_filter, | |
| 98 include_deletes=False) | |
| 99 affected_js_files = filter(lambda f: f.LocalPath().endswith('.js'), | |
| 100 affected_files) | |
| 101 for f in affected_js_files: | |
| 102 error_lines = [] | |
| 103 | |
| 104 for i, line in enumerate(f.NewContents(), start=1): | |
| 105 error_lines += filter(None, [ | |
| 106 self.ChromeSendCheck(i, line), | |
| 107 self.CommentIfAndIncludeCheck(i, line), | |
| 108 self.ConstCheck(i, line), | |
| 109 self.GetElementByIdCheck(i, line), | |
| 110 self.EndJsDocCommentCheck(i, line), | |
| 111 self.ExtraDotInGenericCheck(i, line), | |
| 112 self.InheritDocCheck(i, line), | |
| 113 self.PolymerLocalIdCheck(i, line), | |
| 114 self.WrapperTypeCheck(i, line), | |
| 115 self.VarNameCheck(i, line), | |
| 116 ]) | |
| 117 | |
| 118 if error_lines: | |
| 119 error_lines = [ | |
| 120 'Found JavaScript style violations in %s:' % | |
| 121 f.LocalPath()] + error_lines | |
| 122 results.append(self.output_api.PresubmitError('\n'.join(error_lines))) | |
| 123 | |
| 124 if results: | |
| 125 results.append(self.output_api.PresubmitNotifyResult( | |
| 126 'See the JavaScript style guide at ' | |
| 127 'https://chromium.googlesource.com/chromium/src/+/master/styleguide/we
b/web.md#JavaScript')) | |
| 128 | |
| 129 return results | |
| OLD | NEW |