aboutsummaryrefslogtreecommitdiff
path: root/tools/closure_linter-2.3.4/closure_linter/ecmalintrules.py
diff options
context:
space:
mode:
Diffstat (limited to 'tools/closure_linter-2.3.4/closure_linter/ecmalintrules.py')
-rwxr-xr-xtools/closure_linter-2.3.4/closure_linter/ecmalintrules.py786
1 files changed, 0 insertions, 786 deletions
diff --git a/tools/closure_linter-2.3.4/closure_linter/ecmalintrules.py b/tools/closure_linter-2.3.4/closure_linter/ecmalintrules.py
deleted file mode 100755
index 1187f51..0000000
--- a/tools/closure_linter-2.3.4/closure_linter/ecmalintrules.py
+++ /dev/null
@@ -1,786 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright 2008 The Closure Linter Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS-IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""Core methods for checking EcmaScript files for common style guide violations.
-"""
-
-__author__ = ('robbyw@google.com (Robert Walker)',
- 'ajp@google.com (Andy Perelson)',
- 'jacobr@google.com (Jacob Richman)')
-
-import re
-
-from closure_linter import checkerbase
-from closure_linter import ecmametadatapass
-from closure_linter import error_check
-from closure_linter import errors
-from closure_linter import indentation
-from closure_linter import javascripttokens
-from closure_linter import javascripttokenizer
-from closure_linter import statetracker
-from closure_linter import tokenutil
-from closure_linter.common import error
-from closure_linter.common import htmlutil
-from closure_linter.common import lintrunner
-from closure_linter.common import position
-from closure_linter.common import tokens
-import gflags as flags
-
-FLAGS = flags.FLAGS
-flags.DEFINE_list('custom_jsdoc_tags', '', 'Extra jsdoc tags to allow')
-
-# TODO(robbyw): Check for extra parens on return statements
-# TODO(robbyw): Check for 0px in strings
-# TODO(robbyw): Ensure inline jsDoc is in {}
-# TODO(robbyw): Check for valid JS types in parameter docs
-
-# Shorthand
-Context = ecmametadatapass.EcmaContext
-Error = error.Error
-Modes = javascripttokenizer.JavaScriptModes
-Position = position.Position
-Rule = error_check.Rule
-Type = javascripttokens.JavaScriptTokenType
-
-class EcmaScriptLintRules(checkerbase.LintRulesBase):
- """EmcaScript lint style checking rules.
-
- Can be used to find common style errors in JavaScript, ActionScript and other
- Ecma like scripting languages. Style checkers for Ecma scripting languages
- should inherit from this style checker.
- Please do not add any state to EcmaScriptLintRules or to any subclasses.
-
- All state should be added to the StateTracker subclass used for a particular
- language.
- """
-
- # Static constants.
- MAX_LINE_LENGTH = 80
-
- MISSING_PARAMETER_SPACE = re.compile(r',\S')
-
- EXTRA_SPACE = re.compile('(\(\s|\s\))')
-
- ENDS_WITH_SPACE = re.compile('\s$')
-
- ILLEGAL_TAB = re.compile(r'\t')
-
- # Regex used to split up complex types to check for invalid use of ? and |.
- TYPE_SPLIT = re.compile(r'[,<>()]')
-
- # Regex for form of author lines after the @author tag.
- AUTHOR_SPEC = re.compile(r'(\s*)[^\s]+@[^(\s]+(\s*)\(.+\)')
-
- # Acceptable tokens to remove for line too long testing.
- LONG_LINE_IGNORE = frozenset(['*', '//', '@see'] +
- ['@%s' % tag for tag in statetracker.DocFlag.HAS_TYPE])
-
- def __init__(self):
- """Initialize this lint rule object."""
- checkerbase.LintRulesBase.__init__(self)
-
- def Initialize(self, checker, limited_doc_checks, is_html):
- """Initialize this lint rule object before parsing a new file."""
- checkerbase.LintRulesBase.Initialize(self, checker, limited_doc_checks,
- is_html)
- self._indentation = indentation.IndentationRules()
-
- def HandleMissingParameterDoc(self, token, param_name):
- """Handle errors associated with a parameter missing a @param tag."""
- raise TypeError('Abstract method HandleMissingParameterDoc not implemented')
-
- def _CheckLineLength(self, last_token, state):
- """Checks whether the line is too long.
-
- Args:
- last_token: The last token in the line.
- """
- # Start from the last token so that we have the flag object attached to
- # and DOC_FLAG tokens.
- line_number = last_token.line_number
- token = last_token
-
- # Build a representation of the string where spaces indicate potential
- # line-break locations.
- line = []
- while token and token.line_number == line_number:
- if state.IsTypeToken(token):
- line.insert(0, 'x' * len(token.string))
- elif token.type in (Type.IDENTIFIER, Type.NORMAL):
- # Dots are acceptable places to wrap.
- line.insert(0, token.string.replace('.', ' '))
- else:
- line.insert(0, token.string)
- token = token.previous
-
- line = ''.join(line)
- line = line.rstrip('\n\r\f')
- try:
- length = len(unicode(line, 'utf-8'))
- except:
- # Unknown encoding. The line length may be wrong, as was originally the
- # case for utf-8 (see bug 1735846). For now just accept the default
- # length, but as we find problems we can either add test for other
- # possible encodings or return without an error to protect against
- # false positives at the cost of more false negatives.
- length = len(line)
-
- if length > self.MAX_LINE_LENGTH:
-
- # If the line matches one of the exceptions, then it's ok.
- for long_line_regexp in self.GetLongLineExceptions():
- if long_line_regexp.match(last_token.line):
- return
-
- # If the line consists of only one "word", or multiple words but all
- # except one are ignoreable, then it's ok.
- parts = set(line.split())
-
- # We allow two "words" (type and name) when the line contains @param
- max = 1
- if '@param' in parts:
- max = 2
-
- # Custom tags like @requires may have url like descriptions, so ignore
- # the tag, similar to how we handle @see.
- custom_tags = set(['@%s' % f for f in FLAGS.custom_jsdoc_tags])
- if (len(parts.difference(self.LONG_LINE_IGNORE | custom_tags)) > max):
- self._HandleError(errors.LINE_TOO_LONG,
- 'Line too long (%d characters).' % len(line), last_token)
-
- def _CheckJsDocType(self, token):
- """Checks the given type for style errors.
-
- Args:
- token: The DOC_FLAG token for the flag whose type to check.
- """
- flag = token.attached_object
- type = flag.type
- if type and type is not None and not type.isspace():
- pieces = self.TYPE_SPLIT.split(type)
- if len(pieces) == 1 and type.count('|') == 1 and (
- type.endswith('|null') or type.startswith('null|')):
- self._HandleError(errors.JSDOC_PREFER_QUESTION_TO_PIPE_NULL,
- 'Prefer "?Type" to "Type|null": "%s"' % type, token)
-
- for p in pieces:
- if p.count('|') and p.count('?'):
- # TODO(robbyw): We should do actual parsing of JsDoc types. As is,
- # this won't report an error for {number|Array.<string>?}, etc.
- self._HandleError(errors.JSDOC_ILLEGAL_QUESTION_WITH_PIPE,
- 'JsDoc types cannot contain both "?" and "|": "%s"' % p, token)
-
- if error_check.ShouldCheck(Rule.BRACES_AROUND_TYPE) and (
- flag.type_start_token.type != Type.DOC_START_BRACE or
- flag.type_end_token.type != Type.DOC_END_BRACE):
- self._HandleError(errors.MISSING_BRACES_AROUND_TYPE,
- 'Type must always be surrounded by curly braces.', token)
-
- def _CheckForMissingSpaceBeforeToken(self, token):
- """Checks for a missing space at the beginning of a token.
-
- Reports a MISSING_SPACE error if the token does not begin with a space or
- the previous token doesn't end with a space and the previous token is on the
- same line as the token.
-
- Args:
- token: The token being checked
- """
- # TODO(user): Check if too many spaces?
- if (len(token.string) == len(token.string.lstrip()) and
- token.previous and token.line_number == token.previous.line_number and
- len(token.previous.string) - len(token.previous.string.rstrip()) == 0):
- self._HandleError(
- errors.MISSING_SPACE,
- 'Missing space before "%s"' % token.string,
- token,
- Position.AtBeginning())
-
- def _ExpectSpaceBeforeOperator(self, token):
- """Returns whether a space should appear before the given operator token.
-
- Args:
- token: The operator token.
-
- Returns:
- Whether there should be a space before the token.
- """
- if token.string == ',' or token.metadata.IsUnaryPostOperator():
- return False
-
- # Colons should appear in labels, object literals, the case of a switch
- # statement, and ternary operator. Only want a space in the case of the
- # ternary operator.
- if (token.string == ':' and
- token.metadata.context.type in (Context.LITERAL_ELEMENT,
- Context.CASE_BLOCK,
- Context.STATEMENT)):
- return False
-
- if token.metadata.IsUnaryOperator() and token.IsFirstInLine():
- return False
-
- return True
-
- def CheckToken(self, token, state):
- """Checks a token, given the current parser_state, for warnings and errors.
-
- Args:
- token: The current token under consideration
- state: parser_state object that indicates the current state in the page
- """
- # Store some convenience variables
- first_in_line = token.IsFirstInLine()
- last_in_line = token.IsLastInLine()
- last_non_space_token = state.GetLastNonSpaceToken()
-
- type = token.type
-
- # Process the line change.
- if not self._is_html and error_check.ShouldCheck(Rule.INDENTATION):
- # TODO(robbyw): Support checking indentation in HTML files.
- indentation_errors = self._indentation.CheckToken(token, state)
- for indentation_error in indentation_errors:
- self._HandleError(*indentation_error)
-
- if last_in_line:
- self._CheckLineLength(token, state)
-
- if type == Type.PARAMETERS:
- # Find missing spaces in parameter lists.
- if self.MISSING_PARAMETER_SPACE.search(token.string):
- self._HandleError(errors.MISSING_SPACE, 'Missing space after ","',
- token)
-
- # Find extra spaces at the beginning of parameter lists. Make sure
- # we aren't at the beginning of a continuing multi-line list.
- if not first_in_line:
- space_count = len(token.string) - len(token.string.lstrip())
- if space_count:
- self._HandleError(errors.EXTRA_SPACE, 'Extra space after "("',
- token, Position(0, space_count))
-
- elif (type == Type.START_BLOCK and
- token.metadata.context.type == Context.BLOCK):
- self._CheckForMissingSpaceBeforeToken(token)
-
- elif type == Type.END_BLOCK:
- # This check is for object literal end block tokens, but there is no need
- # to test that condition since a comma at the end of any other kind of
- # block is undoubtedly a parse error.
- last_code = token.metadata.last_code
- if last_code.IsOperator(','):
- self._HandleError(errors.COMMA_AT_END_OF_LITERAL,
- 'Illegal comma at end of object literal', last_code,
- Position.All(last_code.string))
-
- if state.InFunction() and state.IsFunctionClose():
- is_immediately_called = (token.next and
- token.next.type == Type.START_PAREN)
- if state.InTopLevelFunction():
- # When the function was top-level and not immediately called, check
- # that it's terminated by a semi-colon.
- if state.InAssignedFunction():
- if not is_immediately_called and (last_in_line or
- not token.next.type == Type.SEMICOLON):
- self._HandleError(errors.MISSING_SEMICOLON_AFTER_FUNCTION,
- 'Missing semicolon after function assigned to a variable',
- token, Position.AtEnd(token.string))
- else:
- if not last_in_line and token.next.type == Type.SEMICOLON:
- self._HandleError(errors.ILLEGAL_SEMICOLON_AFTER_FUNCTION,
- 'Illegal semicolon after function declaration',
- token.next, Position.All(token.next.string))
-
- if (state.InInterfaceMethod() and last_code.type != Type.START_BLOCK):
- self._HandleError(errors.INTERFACE_METHOD_CANNOT_HAVE_CODE,
- 'Interface methods cannot contain code', last_code)
-
- elif (state.IsBlockClose() and
- token.next and token.next.type == Type.SEMICOLON):
- self._HandleError(errors.REDUNDANT_SEMICOLON,
- 'No semicolon is required to end a code block',
- token.next, Position.All(token.next.string))
-
- elif type == Type.SEMICOLON:
- if token.previous and token.previous.type == Type.WHITESPACE:
- self._HandleError(errors.EXTRA_SPACE, 'Extra space before ";"',
- token.previous, Position.All(token.previous.string))
-
- if token.next and token.next.line_number == token.line_number:
- if token.metadata.context.type != Context.FOR_GROUP_BLOCK:
- # TODO(robbyw): Error about no multi-statement lines.
- pass
-
- elif token.next.type not in (
- Type.WHITESPACE, Type.SEMICOLON, Type.END_PAREN):
- self._HandleError(errors.MISSING_SPACE,
- 'Missing space after ";" in for statement',
- token.next,
- Position.AtBeginning())
-
- last_code = token.metadata.last_code
- if last_code and last_code.type == Type.SEMICOLON:
- # Allow a single double semi colon in for loops for cases like:
- # for (;;) { }.
- # NOTE(user): This is not a perfect check, and will not throw an error
- # for cases like: for (var i = 0;; i < n; i++) {}, but then your code
- # probably won't work either.
- for_token = tokenutil.CustomSearch(last_code,
- lambda token: token.type == Type.KEYWORD and token.string == 'for',
- end_func=lambda token: token.type == Type.SEMICOLON,
- distance=None,
- reverse=True)
-
- if not for_token:
- self._HandleError(errors.REDUNDANT_SEMICOLON, 'Redundant semicolon',
- token, Position.All(token.string))
-
- elif type == Type.START_PAREN:
- if token.previous and token.previous.type == Type.KEYWORD:
- self._HandleError(errors.MISSING_SPACE, 'Missing space before "("',
- token, Position.AtBeginning())
- elif token.previous and token.previous.type == Type.WHITESPACE:
- before_space = token.previous.previous
- if (before_space and before_space.line_number == token.line_number and
- before_space.type == Type.IDENTIFIER):
- self._HandleError(errors.EXTRA_SPACE, 'Extra space before "("',
- token.previous, Position.All(token.previous.string))
-
- elif type == Type.START_BRACKET:
- self._HandleStartBracket(token, last_non_space_token)
- elif type in (Type.END_PAREN, Type.END_BRACKET):
- # Ensure there is no space before closing parentheses, except when
- # it's in a for statement with an omitted section, or when it's at the
- # beginning of a line.
- if (token.previous and token.previous.type == Type.WHITESPACE and
- not token.previous.IsFirstInLine() and
- not (last_non_space_token and last_non_space_token.line_number ==
- token.line_number and
- last_non_space_token.type == Type.SEMICOLON)):
- self._HandleError(errors.EXTRA_SPACE, 'Extra space before "%s"' %
- token.string, token.previous, Position.All(token.previous.string))
-
- if token.type == Type.END_BRACKET:
- last_code = token.metadata.last_code
- if last_code.IsOperator(','):
- self._HandleError(errors.COMMA_AT_END_OF_LITERAL,
- 'Illegal comma at end of array literal', last_code,
- Position.All(last_code.string))
-
- elif type == Type.WHITESPACE:
- if self.ILLEGAL_TAB.search(token.string):
- if token.IsFirstInLine():
- if token.next:
- self._HandleError(errors.ILLEGAL_TAB,
- 'Illegal tab in whitespace before "%s"' % token.next.string,
- token, Position.All(token.string))
- else:
- self._HandleError(errors.ILLEGAL_TAB,
- 'Illegal tab in whitespace',
- token, Position.All(token.string))
- else:
- self._HandleError(errors.ILLEGAL_TAB,
- 'Illegal tab in whitespace after "%s"' % token.previous.string,
- token, Position.All(token.string))
-
- # Check whitespace length if it's not the first token of the line and
- # if it's not immediately before a comment.
- if last_in_line:
- # Check for extra whitespace at the end of a line.
- self._HandleError(errors.EXTRA_SPACE, 'Extra space at end of line',
- token, Position.All(token.string))
- elif not first_in_line and not token.next.IsComment():
- if token.length > 1:
- self._HandleError(errors.EXTRA_SPACE, 'Extra space after "%s"' %
- token.previous.string, token,
- Position(1, len(token.string) - 1))
-
- elif type == Type.OPERATOR:
- last_code = token.metadata.last_code
-
- if not self._ExpectSpaceBeforeOperator(token):
- if (token.previous and token.previous.type == Type.WHITESPACE and
- last_code and last_code.type in (Type.NORMAL, Type.IDENTIFIER)):
- self._HandleError(errors.EXTRA_SPACE,
- 'Extra space before "%s"' % token.string, token.previous,
- Position.All(token.previous.string))
-
- elif (token.previous and
- not token.previous.IsComment() and
- token.previous.type in Type.EXPRESSION_ENDER_TYPES):
- self._HandleError(errors.MISSING_SPACE,
- 'Missing space before "%s"' % token.string, token,
- Position.AtBeginning())
-
- # Check that binary operators are not used to start lines.
- if ((not last_code or last_code.line_number != token.line_number) and
- not token.metadata.IsUnaryOperator()):
- self._HandleError(errors.LINE_STARTS_WITH_OPERATOR,
- 'Binary operator should go on previous line "%s"' % token.string,
- token)
-
- elif type == Type.DOC_FLAG:
- flag = token.attached_object
-
- if flag.flag_type == 'bug':
- # TODO(robbyw): Check for exactly 1 space on the left.
- string = token.next.string.lstrip()
- string = string.split(' ', 1)[0]
-
- if not string.isdigit():
- self._HandleError(errors.NO_BUG_NUMBER_AFTER_BUG_TAG,
- '@bug should be followed by a bug number', token)
-
- elif flag.flag_type == 'suppress':
- if flag.type is None:
- # A syntactically invalid suppress tag will get tokenized as a normal
- # flag, indicating an error.
- self._HandleError(errors.INCORRECT_SUPPRESS_SYNTAX,
- 'Invalid suppress syntax: should be @suppress {errortype}. '
- 'Spaces matter.', token)
- else:
- for suppress_type in flag.type.split('|'):
- if suppress_type not in state.GetDocFlag().SUPPRESS_TYPES:
- self._HandleError(errors.INVALID_SUPPRESS_TYPE,
- 'Invalid suppression type: %s' % suppress_type,
- token)
-
- elif (error_check.ShouldCheck(Rule.WELL_FORMED_AUTHOR) and
- flag.flag_type == 'author'):
- # TODO(user): In non strict mode check the author tag for as much as
- # it exists, though the full form checked below isn't required.
- string = token.next.string
- result = self.AUTHOR_SPEC.match(string)
- if not result:
- self._HandleError(errors.INVALID_AUTHOR_TAG_DESCRIPTION,
- 'Author tag line should be of the form: '
- '@author foo@somewhere.com (Your Name)',
- token.next)
- else:
- # Check spacing between email address and name. Do this before
- # checking earlier spacing so positions are easier to calculate for
- # autofixing.
- num_spaces = len(result.group(2))
- if num_spaces < 1:
- self._HandleError(errors.MISSING_SPACE,
- 'Missing space after email address',
- token.next, Position(result.start(2), 0))
- elif num_spaces > 1:
- self._HandleError(errors.EXTRA_SPACE,
- 'Extra space after email address',
- token.next,
- Position(result.start(2) + 1, num_spaces - 1))
-
- # Check for extra spaces before email address. Can't be too few, if
- # not at least one we wouldn't match @author tag.
- num_spaces = len(result.group(1))
- if num_spaces > 1:
- self._HandleError(errors.EXTRA_SPACE,
- 'Extra space before email address',
- token.next, Position(1, num_spaces - 1))
-
- elif (flag.flag_type in state.GetDocFlag().HAS_DESCRIPTION and
- not self._limited_doc_checks):
- if flag.flag_type == 'param':
- if flag.name is None:
- self._HandleError(errors.MISSING_JSDOC_PARAM_NAME,
- 'Missing name in @param tag', token)
-
- if not flag.description or flag.description is None:
- flag_name = token.type
- if 'name' in token.values:
- flag_name = '@' + token.values['name']
- self._HandleError(errors.MISSING_JSDOC_TAG_DESCRIPTION,
- 'Missing description in %s tag' % flag_name, token)
- else:
- self._CheckForMissingSpaceBeforeToken(flag.description_start_token)
-
- # We want punctuation to be inside of any tags ending a description,
- # so strip tags before checking description. See bug 1127192. Note
- # that depending on how lines break, the real description end token
- # may consist only of stripped html and the effective end token can
- # be different.
- end_token = flag.description_end_token
- end_string = htmlutil.StripTags(end_token.string).strip()
- while (end_string == '' and not
- end_token.type in Type.FLAG_ENDING_TYPES):
- end_token = end_token.previous
- if end_token.type in Type.FLAG_DESCRIPTION_TYPES:
- end_string = htmlutil.StripTags(end_token.string).rstrip()
-
- if not (end_string.endswith('.') or end_string.endswith('?') or
- end_string.endswith('!')):
- # Find the position for the missing punctuation, inside of any html
- # tags.
- desc_str = end_token.string.rstrip()
- while desc_str.endswith('>'):
- start_tag_index = desc_str.rfind('<')
- if start_tag_index < 0:
- break
- desc_str = desc_str[:start_tag_index].rstrip()
- end_position = Position(len(desc_str), 0)
-
- self._HandleError(
- errors.JSDOC_TAG_DESCRIPTION_ENDS_WITH_INVALID_CHARACTER,
- ('%s descriptions must end with valid punctuation such as a '
- 'period.' % token.string),
- end_token, end_position)
-
- if flag.flag_type in state.GetDocFlag().HAS_TYPE:
- if flag.type_start_token is not None:
- self._CheckForMissingSpaceBeforeToken(
- token.attached_object.type_start_token)
-
- if flag.type and flag.type != '' and not flag.type.isspace():
- self._CheckJsDocType(token)
-
- if type in (Type.DOC_FLAG, Type.DOC_INLINE_FLAG):
- if (token.values['name'] not in state.GetDocFlag().LEGAL_DOC and
- token.values['name'] not in FLAGS.custom_jsdoc_tags):
- self._HandleError(errors.INVALID_JSDOC_TAG,
- 'Invalid JsDoc tag: %s' % token.values['name'], token)
-
- if (error_check.ShouldCheck(Rule.NO_BRACES_AROUND_INHERIT_DOC) and
- token.values['name'] == 'inheritDoc' and
- type == Type.DOC_INLINE_FLAG):
- self._HandleError(errors.UNNECESSARY_BRACES_AROUND_INHERIT_DOC,
- 'Unnecessary braces around @inheritDoc',
- token)
-
- elif type == Type.SIMPLE_LVALUE:
- identifier = token.values['identifier']
-
- if ((not state.InFunction() or state.InConstructor()) and
- not state.InParentheses() and not state.InObjectLiteralDescendant()):
- jsdoc = state.GetDocComment()
- if not state.HasDocComment(identifier):
- # Only test for documentation on identifiers with .s in them to
- # avoid checking things like simple variables. We don't require
- # documenting assignments to .prototype itself (bug 1880803).
- if (not state.InConstructor() and
- identifier.find('.') != -1 and not
- identifier.endswith('.prototype') and not
- self._limited_doc_checks):
- comment = state.GetLastComment()
- if not (comment and comment.lower().count('jsdoc inherited')):
- self._HandleError(errors.MISSING_MEMBER_DOCUMENTATION,
- "No docs found for member '%s'" % identifier,
- token);
- elif jsdoc and (not state.InConstructor() or
- identifier.startswith('this.')):
- # We are at the top level and the function/member is documented.
- if identifier.endswith('_') and not identifier.endswith('__'):
- # Can have a private class which inherits documentation from a
- # public superclass.
- #
- # @inheritDoc is deprecated in favor of using @override, and they
- if (jsdoc.HasFlag('override') and not jsdoc.HasFlag('constructor')
- and not ('accessControls' in jsdoc.suppressions)):
- self._HandleError(errors.INVALID_OVERRIDE_PRIVATE,
- '%s should not override a private member.' % identifier,
- jsdoc.GetFlag('override').flag_token)
- if (jsdoc.HasFlag('inheritDoc') and not jsdoc.HasFlag('constructor')
- and not ('accessControls' in jsdoc.suppressions)):
- self._HandleError(errors.INVALID_INHERIT_DOC_PRIVATE,
- '%s should not inherit from a private member.' % identifier,
- jsdoc.GetFlag('inheritDoc').flag_token)
- if (not jsdoc.HasFlag('private') and
- not ('underscore' in jsdoc.suppressions) and not
- ((jsdoc.HasFlag('inheritDoc') or jsdoc.HasFlag('override')) and
- ('accessControls' in jsdoc.suppressions))):
- self._HandleError(errors.MISSING_PRIVATE,
- 'Member "%s" must have @private JsDoc.' %
- identifier, token)
- if jsdoc.HasFlag('private') and 'underscore' in jsdoc.suppressions:
- self._HandleError(errors.UNNECESSARY_SUPPRESS,
- '@suppress {underscore} is not necessary with @private',
- jsdoc.suppressions['underscore'])
- elif (jsdoc.HasFlag('private') and
- not self.InExplicitlyTypedLanguage()):
- # It is convention to hide public fields in some ECMA
- # implementations from documentation using the @private tag.
- self._HandleError(errors.EXTRA_PRIVATE,
- 'Member "%s" must not have @private JsDoc' %
- identifier, token)
-
- # These flags are only legal on localizable message definitions;
- # such variables always begin with the prefix MSG_.
- for f in ('desc', 'hidden', 'meaning'):
- if (jsdoc.HasFlag(f)
- and not identifier.startswith('MSG_')
- and identifier.find('.MSG_') == -1):
- self._HandleError(errors.INVALID_USE_OF_DESC_TAG,
- 'Member "%s" should not have @%s JsDoc' % (identifier, f),
- token)
-
- # Check for illegaly assigning live objects as prototype property values.
- index = identifier.find('.prototype.')
- # Ignore anything with additional .s after the prototype.
- if index != -1 and identifier.find('.', index + 11) == -1:
- equal_operator = tokenutil.SearchExcept(token, Type.NON_CODE_TYPES)
- next_code = tokenutil.SearchExcept(equal_operator, Type.NON_CODE_TYPES)
- if next_code and (
- next_code.type in (Type.START_BRACKET, Type.START_BLOCK) or
- next_code.IsOperator('new')):
- self._HandleError(errors.ILLEGAL_PROTOTYPE_MEMBER_VALUE,
- 'Member %s cannot have a non-primitive value' % identifier,
- token)
-
- elif type == Type.END_PARAMETERS:
- # Find extra space at the end of parameter lists. We check the token
- # prior to the current one when it is a closing paren.
- if (token.previous and token.previous.type == Type.PARAMETERS
- and self.ENDS_WITH_SPACE.search(token.previous.string)):
- self._HandleError(errors.EXTRA_SPACE, 'Extra space before ")"',
- token.previous)
-
- jsdoc = state.GetDocComment()
- if state.GetFunction().is_interface:
- if token.previous and token.previous.type == Type.PARAMETERS:
- self._HandleError(errors.INTERFACE_CONSTRUCTOR_CANNOT_HAVE_PARAMS,
- 'Interface constructor cannot have parameters',
- token.previous)
- elif (state.InTopLevel() and jsdoc and not jsdoc.HasFlag('see')
- and not jsdoc.InheritsDocumentation()
- and not state.InObjectLiteralDescendant() and not
- jsdoc.IsInvalidated()):
- distance, edit = jsdoc.CompareParameters(state.GetParams())
- if distance:
- params_iter = iter(state.GetParams())
- docs_iter = iter(jsdoc.ordered_params)
-
- for op in edit:
- if op == 'I':
- # Insertion.
- # Parsing doc comments is the same for all languages
- # but some languages care about parameters that don't have
- # doc comments and some languages don't care.
- # Languages that don't allow variables to by typed such as
- # JavaScript care but languages such as ActionScript or Java
- # that allow variables to be typed don't care.
- if not self._limited_doc_checks:
- self.HandleMissingParameterDoc(token, params_iter.next())
-
- elif op == 'D':
- # Deletion
- self._HandleError(errors.EXTRA_PARAMETER_DOCUMENTATION,
- 'Found docs for non-existing parameter: "%s"' %
- docs_iter.next(), token)
- elif op == 'S':
- # Substitution
- if not self._limited_doc_checks:
- self._HandleError(errors.WRONG_PARAMETER_DOCUMENTATION,
- 'Parameter mismatch: got "%s", expected "%s"' %
- (params_iter.next(), docs_iter.next()), token)
-
- else:
- # Equality - just advance the iterators
- params_iter.next()
- docs_iter.next()
-
- elif type == Type.STRING_TEXT:
- # If this is the first token after the start of the string, but it's at
- # the end of a line, we know we have a multi-line string.
- if token.previous.type in (Type.SINGLE_QUOTE_STRING_START,
- Type.DOUBLE_QUOTE_STRING_START) and last_in_line:
- self._HandleError(errors.MULTI_LINE_STRING,
- 'Multi-line strings are not allowed', token)
-
-
- # This check is orthogonal to the ones above, and repeats some types, so
- # it is a plain if and not an elif.
- if token.type in Type.COMMENT_TYPES:
- if self.ILLEGAL_TAB.search(token.string):
- self._HandleError(errors.ILLEGAL_TAB,
- 'Illegal tab in comment "%s"' % token.string, token)
-
- trimmed = token.string.rstrip()
- if last_in_line and token.string != trimmed:
- # Check for extra whitespace at the end of a line.
- self._HandleError(errors.EXTRA_SPACE, 'Extra space at end of line',
- token, Position(len(trimmed), len(token.string) - len(trimmed)))
-
- # This check is also orthogonal since it is based on metadata.
- if token.metadata.is_implied_semicolon:
- self._HandleError(errors.MISSING_SEMICOLON,
- 'Missing semicolon at end of line', token)
-
- def _HandleStartBracket(self, token, last_non_space_token):
- """Handles a token that is an open bracket.
-
- Args:
- token: The token to handle.
- last_non_space_token: The last token that was not a space.
- """
- if (not token.IsFirstInLine() and token.previous.type == Type.WHITESPACE and
- last_non_space_token and
- last_non_space_token.type in Type.EXPRESSION_ENDER_TYPES):
- self._HandleError(errors.EXTRA_SPACE, 'Extra space before "["',
- token.previous, Position.All(token.previous.string))
- # If the [ token is the first token in a line we shouldn't complain
- # about a missing space before [. This is because some Ecma script
- # languages allow syntax like:
- # [Annotation]
- # class MyClass {...}
- # So we don't want to blindly warn about missing spaces before [.
- # In the the future, when rules for computing exactly how many spaces
- # lines should be indented are added, then we can return errors for
- # [ tokens that are improperly indented.
- # For example:
- # var someVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongVariableName =
- # [a,b,c];
- # should trigger a proper indentation warning message as [ is not indented
- # by four spaces.
- elif (not token.IsFirstInLine() and token.previous and
- not token.previous.type in (
- [Type.WHITESPACE, Type.START_PAREN, Type.START_BRACKET] +
- Type.EXPRESSION_ENDER_TYPES)):
- self._HandleError(errors.MISSING_SPACE, 'Missing space before "["',
- token, Position.AtBeginning())
-
- def Finalize(self, state, tokenizer_mode):
- last_non_space_token = state.GetLastNonSpaceToken()
- # Check last line for ending with newline.
- if state.GetLastLine() and not (state.GetLastLine().isspace() or
- state.GetLastLine().rstrip('\n\r\f') != state.GetLastLine()):
- self._HandleError(
- errors.FILE_MISSING_NEWLINE,
- 'File does not end with new line. (%s)' % state.GetLastLine(),
- last_non_space_token)
-
- # Check that the mode is not mid comment, argument list, etc.
- if not tokenizer_mode == Modes.TEXT_MODE:
- self._HandleError(
- errors.FILE_IN_BLOCK,
- 'File ended in mode "%s".' % tokenizer_mode,
- last_non_space_token)
-
- try:
- self._indentation.Finalize()
- except Exception, e:
- self._HandleError(
- errors.FILE_DOES_NOT_PARSE,
- str(e),
- last_non_space_token)
-
- def GetLongLineExceptions(self):
- """Gets a list of regexps for lines which can be longer than the limit."""
- return []
-
- def InExplicitlyTypedLanguage(self):
- """Returns whether this ecma implementation is explicitly typed."""
- return False