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

Unified Diff: third_party/closure_linter/closure_linter/javascriptlintrules.py

Issue 411243002: closure_linter: 2.3.4 => 2.3.14 (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: remove checker Created 6 years, 5 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 side-by-side diff with in-line comments
Download patch
Index: third_party/closure_linter/closure_linter/javascriptlintrules.py
diff --git a/third_party/closure_linter/closure_linter/javascriptlintrules.py b/third_party/closure_linter/closure_linter/javascriptlintrules.py
index d72fd56a54d56cbbdcf4a61ec134748775cc6b04..6406ff799b63b81cf36a31d820aec740db041445 100755
--- a/third_party/closure_linter/closure_linter/javascriptlintrules.py
+++ b/third_party/closure_linter/closure_linter/javascriptlintrules.py
@@ -1,5 +1,4 @@
#!/usr/bin/env python
-#
# Copyright 2011 The Closure Linter Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -25,7 +24,7 @@ __author__ = ('robbyw@google.com (Robert Walker)',
'jacobr@google.com (Jacob Richman)')
import re
-from sets import Set
+
from closure_linter import ecmalintrules
from closure_linter import error_check
from closure_linter import errors
@@ -51,8 +50,12 @@ class JavaScriptLintRules(ecmalintrules.EcmaScriptLintRules):
ecmalintrules.EcmaScriptLintRules.__init__(self)
self._namespaces_info = namespaces_info
self._declared_private_member_tokens = {}
- self._declared_private_members = Set()
- self._used_private_members = Set()
+ self._declared_private_members = set()
+ self._used_private_members = set()
+ # A stack of dictionaries, one for each function scope entered. Each
+ # dictionary is keyed by an identifier that defines a local variable and has
+ # a token as its value.
+ self._unused_local_variables_by_scope = []
def HandleMissingParameterDoc(self, token, param_name):
"""Handle errors associated with a parameter missing a param tag."""
@@ -75,6 +78,7 @@ class JavaScriptLintRules(ecmalintrules.EcmaScriptLintRules):
token.attached_object.type is not None and
token.attached_object.type.find('{') != token.string.rfind('{'))
+ # pylint: disable=too-many-statements
def CheckToken(self, token, state):
"""Checks a token, given the current parser_state, for warnings and errors.
@@ -82,7 +86,10 @@ class JavaScriptLintRules(ecmalintrules.EcmaScriptLintRules):
token: The current token under consideration
state: parser_state object that indicates the current state in the page
"""
- if self.__ContainsRecordType(token):
+
+ # For @param don't ignore record type.
+ if (self.__ContainsRecordType(token) and
+ token.attached_object.flag_type != 'param'):
# We should bail out and not emit any warnings for this annotation.
# TODO(nicksantos): Support record types for real.
state.GetDocComment().Invalidate()
@@ -94,6 +101,9 @@ class JavaScriptLintRules(ecmalintrules.EcmaScriptLintRules):
# Store some convenience variables
namespaces_info = self._namespaces_info
+ if error_check.ShouldCheck(Rule.UNUSED_LOCAL_VARIABLES):
+ self._CheckUnusedLocalVariables(token, state)
+
if error_check.ShouldCheck(Rule.UNUSED_PRIVATE_MEMBERS):
# Find all assignments to private members.
if token.type == Type.SIMPLE_LVALUE:
@@ -101,14 +111,20 @@ class JavaScriptLintRules(ecmalintrules.EcmaScriptLintRules):
if identifier.endswith('_') and not identifier.endswith('__'):
doc_comment = state.GetDocComment()
suppressed = (doc_comment and doc_comment.HasFlag('suppress') and
- doc_comment.GetFlag('suppress').type == 'underscore')
+ (doc_comment.GetFlag('suppress').type == 'underscore' or
+ doc_comment.GetFlag('suppress').type ==
+ 'unusedPrivateMembers'))
if not suppressed:
# Look for static members defined on a provided namespace.
- namespace = namespaces_info.GetClosurizedNamespace(identifier)
- provided_namespaces = namespaces_info.GetProvidedNamespaces()
+ if namespaces_info:
+ namespace = namespaces_info.GetClosurizedNamespace(identifier)
+ provided_namespaces = namespaces_info.GetProvidedNamespaces()
+ else:
+ namespace = None
+ provided_namespaces = set()
# Skip cases of this.something_.somethingElse_.
- regex = re.compile('^this\.[a-zA-Z_]+$')
+ regex = re.compile(r'^this\.[a-zA-Z_]+$')
if namespace in provided_namespaces or regex.match(identifier):
variable = identifier.split('.')[-1]
self._declared_private_member_tokens[variable] = token
@@ -132,27 +148,45 @@ class JavaScriptLintRules(ecmalintrules.EcmaScriptLintRules):
self._CheckForMissingSpaceBeforeToken(
token.attached_object.name_token)
- if (error_check.ShouldCheck(Rule.OPTIONAL_TYPE_MARKER) and
- flag.type is not None and flag.name is not None):
- # Check for optional marker in type.
- if (flag.type.endswith('=') and
- not flag.name.startswith('opt_')):
- self._HandleError(errors.JSDOC_MISSING_OPTIONAL_PREFIX,
- 'Optional parameter name %s must be prefixed '
- 'with opt_.' % flag.name,
- token)
- elif (not flag.type.endswith('=') and
- flag.name.startswith('opt_')):
- self._HandleError(errors.JSDOC_MISSING_OPTIONAL_TYPE,
- 'Optional parameter %s type must end with =.' %
- flag.name,
- token)
+ if flag.type is not None and flag.name is not None:
+ if error_check.ShouldCheck(Rule.VARIABLE_ARG_MARKER):
+ # Check for variable arguments marker in type.
+ if (flag.type.startswith('...') and
+ flag.name != 'var_args'):
+ self._HandleError(errors.JSDOC_MISSING_VAR_ARGS_NAME,
+ 'Variable length argument %s must be renamed '
+ 'to var_args.' % flag.name,
+ token)
+ elif (not flag.type.startswith('...') and
+ flag.name == 'var_args'):
+ self._HandleError(errors.JSDOC_MISSING_VAR_ARGS_TYPE,
+ 'Variable length argument %s type must start '
+ 'with \'...\'.' % flag.name,
+ token)
+
+ if error_check.ShouldCheck(Rule.OPTIONAL_TYPE_MARKER):
+ # Check for optional marker in type.
+ if (flag.type.endswith('=') and
+ not flag.name.startswith('opt_')):
+ self._HandleError(errors.JSDOC_MISSING_OPTIONAL_PREFIX,
+ 'Optional parameter name %s must be prefixed '
+ 'with opt_.' % flag.name,
+ token)
+ elif (not flag.type.endswith('=') and
+ flag.name.startswith('opt_')):
+ self._HandleError(errors.JSDOC_MISSING_OPTIONAL_TYPE,
+ 'Optional parameter %s type must end with =.' %
+ flag.name,
+ token)
if flag.flag_type in state.GetDocFlag().HAS_TYPE:
# Check for both missing type token and empty type braces '{}'
- # Missing suppress types are reported separately and we allow enums
- # without types.
- if (flag.flag_type not in ('suppress', 'enum') and
+ # Missing suppress types are reported separately and we allow enums,
+ # const, private, public and protected without types.
+ allowed_flags = set(['suppress']).union(
+ state.GetDocFlag().CAN_OMIT_TYPE)
+
+ if (flag.flag_type not in allowed_flags and
(not flag.type or flag.type.isspace())):
self._HandleError(errors.MISSING_JSDOC_TAG_TYPE,
'Missing type in %s tag' % token.string, token)
@@ -176,7 +210,7 @@ class JavaScriptLintRules(ecmalintrules.EcmaScriptLintRules):
errors.UNNECESSARY_DOUBLE_QUOTED_STRING,
'Single-quoted string preferred over double-quoted string.',
token,
- Position.All(token.string))
+ position=Position.All(token.string))
elif token.type == Type.END_DOC_COMMENT:
doc_comment = state.GetDocComment()
@@ -187,13 +221,19 @@ class JavaScriptLintRules(ecmalintrules.EcmaScriptLintRules):
self._SetLimitedDocChecks(True)
if (error_check.ShouldCheck(Rule.BLANK_LINES_AT_TOP_LEVEL) and
- not self._is_html and state.InTopLevel() and not state.InBlock()):
+ not self._is_html and
+ state.InTopLevel() and
+ not state.InNonScopeBlock()):
# Check if we're in a fileoverview or constructor JsDoc.
is_constructor = (
doc_comment.HasFlag('constructor') or
doc_comment.HasFlag('interface'))
- is_file_overview = doc_comment.HasFlag('fileoverview')
+ # @fileoverview is an optional tag so if the dosctring is the first
+ # token in the file treat it as a file level docstring.
+ is_file_level_comment = (
+ doc_comment.HasFlag('fileoverview') or
+ not doc_comment.start_token.previous)
# If the comment is not a file overview, and it does not immediately
# precede some code, skip it.
@@ -201,7 +241,8 @@ class JavaScriptLintRules(ecmalintrules.EcmaScriptLintRules):
# behavior at the top of a file.
next_token = token.next
if (not next_token or
- (not is_file_overview and next_token.type in Type.NON_CODE_TYPES)):
+ (not is_file_level_comment and
+ next_token.type in Type.NON_CODE_TYPES)):
return
# Don't require extra blank lines around suppression of extra
@@ -214,7 +255,7 @@ class JavaScriptLintRules(ecmalintrules.EcmaScriptLintRules):
# Find the start of this block (include comments above the block, unless
# this is a file overview).
block_start = doc_comment.start_token
- if not is_file_overview:
+ if not is_file_level_comment:
token = block_start.previous
while token and token.type in Type.COMMENT_TYPES:
block_start = token
@@ -236,22 +277,25 @@ class JavaScriptLintRules(ecmalintrules.EcmaScriptLintRules):
error_message = False
expected_blank_lines = 0
- if is_file_overview and blank_lines == 0:
+ # Only need blank line before file overview if it is not the beginning
+ # of the file, e.g. copyright is first.
+ if is_file_level_comment and blank_lines == 0 and block_start.previous:
error_message = 'Should have a blank line before a file overview.'
expected_blank_lines = 1
elif is_constructor and blank_lines != 3:
error_message = (
'Should have 3 blank lines before a constructor/interface.')
expected_blank_lines = 3
- elif not is_file_overview and not is_constructor and blank_lines != 2:
+ elif (not is_file_level_comment and not is_constructor and
+ blank_lines != 2):
error_message = 'Should have 2 blank lines between top-level blocks.'
expected_blank_lines = 2
if error_message:
self._HandleError(
errors.WRONG_BLANK_LINE_COUNT, error_message,
- block_start, Position.AtBeginning(),
- expected_blank_lines - blank_lines)
+ block_start, position=Position.AtBeginning(),
+ fix_data=expected_blank_lines - blank_lines)
elif token.type == Type.END_BLOCK:
if state.InFunction() and state.IsFunctionClose():
@@ -269,7 +313,7 @@ class JavaScriptLintRules(ecmalintrules.EcmaScriptLintRules):
self._HandleError(
errors.MISSING_RETURN_DOCUMENTATION,
'Missing @return JsDoc in function with non-trivial return',
- function.doc.end_token, Position.AtBeginning())
+ function.doc.end_token, position=Position.AtBeginning())
elif (not function.has_return and
not function.has_throw and
function.doc and
@@ -283,23 +327,63 @@ class JavaScriptLintRules(ecmalintrules.EcmaScriptLintRules):
self._HandleError(
errors.UNNECESSARY_RETURN_DOCUMENTATION,
'Found @return JsDoc on function that returns nothing',
- return_flag.flag_token, Position.AtBeginning())
+ return_flag.flag_token, position=Position.AtBeginning())
+
+ # b/4073735. Method in object literal definition of prototype can
+ # safely reference 'this'.
+ prototype_object_literal = False
+ block_start = None
+ previous_code = None
+ previous_previous_code = None
+
+ # Search for cases where prototype is defined as object literal.
+ # previous_previous_code
+ # | previous_code
+ # | | block_start
+ # | | |
+ # a.b.prototype = {
+ # c : function() {
+ # this.d = 1;
+ # }
+ # }
+
+ # If in object literal, find first token of block so to find previous
+ # tokens to check above condition.
+ if state.InObjectLiteral():
+ block_start = state.GetCurrentBlockStart()
+
+ # If an object literal then get previous token (code type). For above
+ # case it should be '='.
+ if block_start:
+ previous_code = tokenutil.SearchExcept(block_start,
+ Type.NON_CODE_TYPES,
+ reverse=True)
+
+ # If previous token to block is '=' then get its previous token.
+ if previous_code and previous_code.IsOperator('='):
+ previous_previous_code = tokenutil.SearchExcept(previous_code,
+ Type.NON_CODE_TYPES,
+ reverse=True)
+
+ # If variable/token before '=' ends with '.prototype' then its above
+ # case of prototype defined with object literal.
+ prototype_object_literal = (previous_previous_code and
+ previous_previous_code.string.endswith(
+ '.prototype'))
- if state.InFunction() and state.IsFunctionClose():
- is_immediately_called = (token.next and
- token.next.type == Type.START_PAREN)
if (function.has_this and function.doc and
not function.doc.HasFlag('this') and
not function.is_constructor and
not function.is_interface and
- '.prototype.' not in function.name):
+ '.prototype.' not in function.name and
+ not prototype_object_literal):
self._HandleError(
errors.MISSING_JSDOC_TAG_THIS,
'Missing @this JsDoc in function referencing "this". ('
'this usually means you are trying to reference "this" in '
'a static function, or you have forgotten to mark a '
'constructor with @constructor)',
- function.doc.end_token, Position.AtBeginning())
+ function.doc.end_token, position=Position.AtBeginning())
elif token.type == Type.IDENTIFIER:
if token.string == 'goog.inherits' and not state.InFunction():
@@ -308,7 +392,7 @@ class JavaScriptLintRules(ecmalintrules.EcmaScriptLintRules):
errors.MISSING_LINE,
'Missing newline between constructor and goog.inherits',
token,
- Position.AtBeginning())
+ position=Position.AtBeginning())
extra_space = state.GetLastNonSpaceToken().next
while extra_space != token:
@@ -325,13 +409,23 @@ class JavaScriptLintRules(ecmalintrules.EcmaScriptLintRules):
elif (token.string == 'goog.provide' and
not state.InFunction() and
namespaces_info is not None):
- namespace = tokenutil.Search(token, Type.STRING_TEXT).string
+ namespace = tokenutil.GetStringAfterToken(token)
# Report extra goog.provide statement.
- if namespaces_info.IsExtraProvide(token):
+ if not namespace or namespaces_info.IsExtraProvide(token):
+ if not namespace:
+ msg = 'Empty namespace in goog.provide'
+ else:
+ msg = 'Unnecessary goog.provide: ' + namespace
+
+ # Hint to user if this is a Test namespace.
+ if namespace.endswith('Test'):
+ msg += (' *Test namespaces must be mentioned in the '
+ 'goog.setTestOnly() call')
+
self._HandleError(
errors.EXTRA_GOOG_PROVIDE,
- 'Unnecessary goog.provide: ' + namespace,
+ msg,
token, position=Position.AtBeginning())
if namespaces_info.IsLastProvide(token):
@@ -356,7 +450,7 @@ class JavaScriptLintRules(ecmalintrules.EcmaScriptLintRules):
elif (token.string == 'goog.require' and
not state.InFunction() and
namespaces_info is not None):
- namespace = tokenutil.Search(token, Type.STRING_TEXT).string
+ namespace = tokenutil.GetStringAfterToken(token)
# If there are no provide statements, missing provides should be
# reported before the first require.
@@ -370,10 +464,15 @@ class JavaScriptLintRules(ecmalintrules.EcmaScriptLintRules):
True)
# Report extra goog.require statement.
- if namespaces_info.IsExtraRequire(token):
+ if not namespace or namespaces_info.IsExtraRequire(token):
+ if not namespace:
+ msg = 'Empty namespace in goog.require'
+ else:
+ msg = 'Unnecessary goog.require: ' + namespace
+
self._HandleError(
errors.EXTRA_GOOG_REQUIRE,
- 'Unnecessary goog.require: ' + namespace,
+ msg,
token, position=Position.AtBeginning())
# Report missing goog.require statements.
@@ -395,14 +494,14 @@ class JavaScriptLintRules(ecmalintrules.EcmaScriptLintRules):
if (not token.metadata.IsUnaryOperator() and not last_in_line
and not token.next.IsComment()
and not token.next.IsOperator(',')
- and not token.next.type in (Type.WHITESPACE, Type.END_PAREN,
+ and token.next.type not in (Type.WHITESPACE, Type.END_PAREN,
Type.END_BRACKET, Type.SEMICOLON,
Type.START_BRACKET)):
self._HandleError(
errors.MISSING_SPACE,
'Missing space after "%s"' % token.string,
token,
- Position.AtEnd(token.string))
+ position=Position.AtEnd(token.string))
elif token.type == Type.WHITESPACE:
first_in_line = token.IsFirstInLine()
last_in_line = token.IsLastInLine()
@@ -417,52 +516,152 @@ class JavaScriptLintRules(ecmalintrules.EcmaScriptLintRules):
errors.EXTRA_SPACE,
'Extra space after "%s"' % token.previous.string,
token,
- Position.All(token.string))
+ position=Position.All(token.string))
+ elif token.type == Type.SEMICOLON:
+ previous_token = tokenutil.SearchExcept(token, Type.NON_CODE_TYPES,
+ reverse=True)
+ if not previous_token:
+ self._HandleError(
+ errors.REDUNDANT_SEMICOLON,
+ 'Semicolon without any statement',
+ token,
+ position=Position.AtEnd(token.string))
+ elif (previous_token.type == Type.KEYWORD and
+ previous_token.string not in ['break', 'continue', 'return']):
+ self._HandleError(
+ errors.REDUNDANT_SEMICOLON,
+ ('Semicolon after \'%s\' without any statement.'
+ ' Looks like an error.' % previous_token.string),
+ token,
+ position=Position.AtEnd(token.string))
+
+ def _CheckUnusedLocalVariables(self, token, state):
+ """Checks for unused local variables in function blocks.
+
+ Args:
+ token: The token to check.
+ state: The state tracker.
+ """
+ # We don't use state.InFunction because that disregards scope functions.
+ in_function = state.FunctionDepth() > 0
+ if token.type == Type.SIMPLE_LVALUE or token.type == Type.IDENTIFIER:
+ if in_function:
+ identifier = token.string
+ # Check whether the previous token was var.
+ previous_code_token = tokenutil.CustomSearch(
+ token,
+ lambda t: t.type not in Type.NON_CODE_TYPES,
+ reverse=True)
+ if previous_code_token and previous_code_token.IsKeyword('var'):
+ # Add local variable declaration to the top of the unused locals
+ # stack.
+ self._unused_local_variables_by_scope[-1][identifier] = token
+ elif token.type == Type.IDENTIFIER:
+ # This covers most cases where the variable is used as an identifier.
+ self._MarkLocalVariableUsed(token)
+ elif token.type == Type.SIMPLE_LVALUE and '.' in identifier:
+ # This covers cases where a value is assigned to a property of the
+ # variable.
+ self._MarkLocalVariableUsed(token)
+ elif token.type == Type.START_BLOCK:
+ if in_function and state.IsFunctionOpen():
+ # Push a new map onto the stack
+ self._unused_local_variables_by_scope.append({})
+ elif token.type == Type.END_BLOCK:
+ if state.IsFunctionClose():
+ # Pop the stack and report any remaining locals as unused.
+ unused_local_variables = self._unused_local_variables_by_scope.pop()
+ for unused_token in unused_local_variables.values():
+ self._HandleError(
+ errors.UNUSED_LOCAL_VARIABLE,
+ 'Unused local variable: %s.' % unused_token.string,
+ unused_token)
+
+ def _MarkLocalVariableUsed(self, token):
+ """Marks the local variable as used in the relevant scope.
+
+ Marks the local variable as used in the scope nearest to the current
+ scope that matches the given token.
+
+ Args:
+ token: The token representing the potential usage of a local variable.
+ """
+
+ identifier = token.string.split('.')[0]
+ # Find the first instance of the identifier in the stack of function scopes
+ # and mark it used.
+ for unused_local_variables in reversed(
+ self._unused_local_variables_by_scope):
+ if identifier in unused_local_variables:
+ del unused_local_variables[identifier]
+ break
def _ReportMissingProvides(self, missing_provides, token, need_blank_line):
"""Reports missing provide statements to the error handler.
Args:
- missing_provides: A list of strings where each string is a namespace that
- should be provided, but is not.
+ missing_provides: A dictionary of string(key) and integer(value) where
+ each string(key) is a namespace that should be provided, but is not
+ and integer(value) is first line number where it's required.
token: The token where the error was detected (also where the new provides
will be inserted.
need_blank_line: Whether a blank line needs to be inserted after the new
provides are inserted. May be True, False, or None, where None
indicates that the insert location is unknown.
"""
+
+ missing_provides_msg = 'Missing the following goog.provide statements:\n'
+ missing_provides_msg += '\n'.join(['goog.provide(\'%s\');' % x for x in
+ sorted(missing_provides)])
+ missing_provides_msg += '\n'
+
+ missing_provides_msg += '\nFirst line where provided: \n'
+ missing_provides_msg += '\n'.join(
+ [' %s : line %d' % (x, missing_provides[x]) for x in
+ sorted(missing_provides)])
+ missing_provides_msg += '\n'
+
self._HandleError(
errors.MISSING_GOOG_PROVIDE,
- 'Missing the following goog.provide statements:\n' +
- '\n'.join(map(lambda x: 'goog.provide(\'%s\');' % x,
- sorted(missing_provides))),
+ missing_provides_msg,
token, position=Position.AtBeginning(),
- fix_data=(missing_provides, need_blank_line))
+ fix_data=(missing_provides.keys(), need_blank_line))
def _ReportMissingRequires(self, missing_requires, token, need_blank_line):
"""Reports missing require statements to the error handler.
Args:
- missing_requires: A list of strings where each string is a namespace that
- should be required, but is not.
+ missing_requires: A dictionary of string(key) and integer(value) where
+ each string(key) is a namespace that should be required, but is not
+ and integer(value) is first line number where it's required.
token: The token where the error was detected (also where the new requires
will be inserted.
need_blank_line: Whether a blank line needs to be inserted before the new
requires are inserted. May be True, False, or None, where None
indicates that the insert location is unknown.
"""
+
+ missing_requires_msg = 'Missing the following goog.require statements:\n'
+ missing_requires_msg += '\n'.join(['goog.require(\'%s\');' % x for x in
+ sorted(missing_requires)])
+ missing_requires_msg += '\n'
+
+ missing_requires_msg += '\nFirst line where required: \n'
+ missing_requires_msg += '\n'.join(
+ [' %s : line %d' % (x, missing_requires[x]) for x in
+ sorted(missing_requires)])
+ missing_requires_msg += '\n'
+
self._HandleError(
errors.MISSING_GOOG_REQUIRE,
- 'Missing the following goog.require statements:\n' +
- '\n'.join(map(lambda x: 'goog.require(\'%s\');' % x,
- sorted(missing_requires))),
+ missing_requires_msg,
token, position=Position.AtBeginning(),
- fix_data=(missing_requires, need_blank_line))
+ fix_data=(missing_requires.keys(), need_blank_line))
- def Finalize(self, state, tokenizer_mode):
+ def Finalize(self, state):
"""Perform all checks that need to occur after all lines are processed."""
# Call the base class's Finalize function.
- super(JavaScriptLintRules, self).Finalize(state, tokenizer_mode)
+ super(JavaScriptLintRules, self).Finalize(state)
if error_check.ShouldCheck(Rule.UNUSED_PRIVATE_MEMBERS):
# Report an error for any declared private member that was never used.
@@ -477,8 +676,8 @@ class JavaScriptLintRules(ecmalintrules.EcmaScriptLintRules):
# Clear state to prepare for the next file.
self._declared_private_member_tokens = {}
- self._declared_private_members = Set()
- self._used_private_members = Set()
+ self._declared_private_members = set()
+ self._used_private_members = set()
namespaces_info = self._namespaces_info
if namespaces_info is not None:
@@ -508,31 +707,37 @@ class JavaScriptLintRules(ecmalintrules.EcmaScriptLintRules):
token: The first token in the token stream.
"""
sorter = requireprovidesorter.RequireProvideSorter()
- provides_result = sorter.CheckProvides(token)
- if provides_result:
+ first_provide_token = sorter.CheckProvides(token)
+ if first_provide_token:
+ new_order = sorter.GetFixedProvideString(first_provide_token)
self._HandleError(
errors.GOOG_PROVIDES_NOT_ALPHABETIZED,
'goog.provide classes must be alphabetized. The correct code is:\n' +
- '\n'.join(
- map(lambda x: 'goog.provide(\'%s\');' % x, provides_result[1])),
- provides_result[0],
+ new_order,
+ first_provide_token,
position=Position.AtBeginning(),
- fix_data=provides_result[0])
+ fix_data=first_provide_token)
- requires_result = sorter.CheckRequires(token)
- if requires_result:
+ first_require_token = sorter.CheckRequires(token)
+ if first_require_token:
+ new_order = sorter.GetFixedRequireString(first_require_token)
self._HandleError(
errors.GOOG_REQUIRES_NOT_ALPHABETIZED,
'goog.require classes must be alphabetized. The correct code is:\n' +
- '\n'.join(
- map(lambda x: 'goog.require(\'%s\');' % x, requires_result[1])),
- requires_result[0],
+ new_order,
+ first_require_token,
position=Position.AtBeginning(),
- fix_data=requires_result[0])
+ fix_data=first_require_token)
def GetLongLineExceptions(self):
- """Gets a list of regexps for lines which can be longer than the limit."""
+ """Gets a list of regexps for lines which can be longer than the limit.
+
+ Returns:
+ A list of regexps, used as matches (rather than searches).
+ """
return [
- re.compile('goog\.require\(.+\);?\s*$'),
- re.compile('goog\.provide\(.+\);?\s*$')
+ re.compile(r'goog\.require\(.+\);?\s*$'),
+ re.compile(r'goog\.provide\(.+\);?\s*$'),
+ re.compile(r'goog\.setTestOnly\(.+\);?\s*$'),
+ re.compile(r'[\s/*]*@visibility\s*{.*}[\s*/]*$'),
]

Powered by Google App Engine
This is Rietveld 408576698