[javascriptlint-commit] SF.net SVN: javascriptlint: [198] trunk/pyjsl
Status: Beta
Brought to you by:
matthiasmiller
|
From: <mat...@us...> - 2008-04-26 05:09:32
|
Revision: 198
http://javascriptlint.svn.sourceforge.net/javascriptlint/?rev=198&view=rev
Author: matthiasmiller
Date: 2008-04-25 22:09:30 -0700 (Fri, 25 Apr 2008)
Log Message:
-----------
Change the visitors to be functions instead of classes.
Modified Paths:
--------------
trunk/pyjsl/conf.py
trunk/pyjsl/lint.py
trunk/pyjsl/warnings.py
Modified: trunk/pyjsl/conf.py
===================================================================
--- trunk/pyjsl/conf.py 2008-04-26 04:40:07 UTC (rev 197)
+++ trunk/pyjsl/conf.py 2008-04-26 05:09:30 UTC (rev 198)
@@ -68,8 +68,8 @@
'equal_as_assign': BooleanSetting(True),
'anon_no_return_value': BooleanSetting(True)
}
- for klass in warnings.klasses:
- self._settings[klass.__name__] = BooleanSetting(True)
+ for name in warnings.warnings:
+ self._settings[name] = BooleanSetting(True)
self.loadline('-block_without_braces')
def loadfile(self, path):
Modified: trunk/pyjsl/lint.py
===================================================================
--- trunk/pyjsl/lint.py 2008-04-26 04:40:07 UTC (rev 197)
+++ trunk/pyjsl/lint.py 2008-04-26 05:09:30 UTC (rev 198)
@@ -218,8 +218,9 @@
_report(pos, msg, False)
# Find all visitors and convert them into "onpush" callbacks that call "report"
- visitors = {}
- visitation.make_visitors(visitors, warnings.klasses)
+ visitors = {
+ 'push': warnings.make_visitors()
+ }
for event in visitors:
for kind, callbacks in visitors[event].items():
visitors[event][kind] = [_getreporter(callback, report) for callback in callbacks]
@@ -259,7 +260,7 @@
ret = visitor(node)
assert ret is None, 'visitor should raise an exception, not return a value'
except warnings.LintWarning, warning:
- report(warning.node, visitor.im_class.__name__)
+ report(warning.node, visitor.warning)
return onpush
def _warn_or_declare(scope, name, node, report):
Modified: trunk/pyjsl/warnings.py
===================================================================
--- trunk/pyjsl/warnings.py 2008-04-26 04:40:07 UTC (rev 197)
+++ trunk/pyjsl/warnings.py 2008-04-26 05:09:30 UTC (rev 198)
@@ -1,22 +1,18 @@
# vim: ts=4 sw=4 expandtab
""" This module contains all the warnings. To add a new warning, define a
-class. Its name should be in lowercase and words should be separated by
-underscores. Its docstring should be the warning message.
+function. Its name should be in lowercase and words should be separated by
+underscores.
-The class can have one more more member functions to inspect nodes. The
-function should be decorated with a @onpush call specifying the nodes it
+The function should be decorated with a @lookfor call specifying the nodes it
wants to examine. The node names may be in the tok.KIND or (tok.KIND, op.OPCODE)
-format. To report a warning, the function should return the node causing
-the warning.
+format. To report a warning, the function should raise a LintWarning exception.
For example:
- class warning_name:
- 'questionable JavaScript coding style'
- @onpush(tok.NODEKIND, (tok.NODEKIND, op.OPCODE))
- def _lint(self, node):
- if questionable:
- return node
+ @lookfor(tok.NODEKIND, (tok.NODEKIND, op.OPCODE))
+ def warning_name(node):
+ if questionable:
+ raise LintWarning, node
"""
import re
import sys
@@ -27,9 +23,59 @@
# TODO: document inspect, node:opcode, etc
-def onpush(*args):
- return visitation.visit('push', *args)
+warnings = {
+ 'comparison_type_conv': 'comparisons against null, 0, true, false, or an empty string allowing implicit type conversion (use === or !==)',
+ 'default_not_at_end': 'the default case is not at the end of the switch statement',
+ 'duplicate_case_in_switch': 'duplicate case in switch statement',
+ 'missing_default_case': 'missing default case in switch statement',
+ 'with_statement': 'with statement hides undeclared variables; use temporary variable instead',
+ 'useless_comparison': 'useless comparison; comparing identical expressions',
+ 'use_of_label': 'use of label',
+ 'meaningless_block': 'meaningless block; curly braces have no impact',
+ 'misplaced_regex': 'regular expressions should be preceded by a left parenthesis, assignment, colon, or comma',
+ 'assign_to_function_call': 'assignment to a function call',
+ 'ambiguous_else_stmt': 'the else statement could be matched with one of multiple if statements (use curly braces to indicate intent',
+ 'block_without_braces': 'block statement without curly braces',
+ 'ambiguous_nested_stmt': 'block statements containing block statements should use curly braces to resolve ambiguity',
+ 'inc_dec_within_stmt': 'increment (++) and decrement (--) operators used as part of greater statement',
+ 'comma_separated_stmts': 'multiple statements separated by commas (use semicolons?)',
+ 'empty_statement': 'empty statement or extra semicolon',
+ 'missing_break': 'missing break statement',
+ 'missing_break_for_last_case': 'missing break statement for last case in switch',
+ 'multiple_plus_minus': 'unknown order of operations for successive plus (e.g. x+++y) or minus (e.g. x---y) signs',
+ 'useless_assign': 'useless assignment',
+ 'unreachable_code': 'unreachable code',
+ 'meaningless_block': 'meaningless block; curly braces have no impact',
+ 'useless_void': 'use of the void type may be unnecessary (void is always undefined)',
+ 'parseint_missing_radix': 'parseInt missing radix parameter',
+ 'leading_decimal_point': 'leading decimal point may indicate a number or an object member',
+ 'trailing_decimal_point': 'trailing decimal point may indicate a number or an object member',
+ 'octal_number': 'leading zeros make an octal number',
+ 'trailing_comma_in_array': 'extra comma is not recommended in array initializers',
+ 'useless_quotes': 'the quotation marks are unnecessary',
+ 'mismatch_ctrl_comments': 'mismatched control comment; "ignore" and "end" control comments must have a one-to-one correspondence',
+ 'redeclared_var': 'redeclaration of {0} {1}',
+ 'undeclared_identifier': 'undeclared identifier: {0}',
+ 'jsl_cc_not_understood': 'couldn\'t understand control comment using /*jsl:keyword*/ syntax',
+ 'nested_comment': 'nested comment',
+ 'legacy_cc_not_understood': 'couldn\'t understand control comment using /*@keyword@*/ syntax',
+ 'var_hides_arg': 'variable {0} hides argument',
+ 'duplicate_formal': 'TODO',
+ 'missing_semicolon': 'missing semicolon',
+ 'ambiguous_newline': 'unexpected end of line; it is ambiguous whether these lines are part of the same statement',
+ 'missing_option_explicit': 'the "option explicit" control comment is missing',
+ 'partial_option_explicit': 'the "option explicit" control comment, if used, must be in the first script tag',
+ 'dup_option_explicit': 'duplicate "option explicit" control comment',
+}
+def lookfor(*args):
+ def decorate(fn):
+ fn._lint_nodes = args
+ fn.warning = fn.func_name.rstrip('_')
+ assert fn.warning in warnings, 'Missing warning description: %s' % fn.warning
+ return fn
+ return decorate
+
class LintWarning(Exception):
def __init__(self, node):
self.node = node
@@ -124,382 +170,325 @@
return exit_points
-class comparison_type_conv:
- 'comparisons against null, 0, true, false, or an empty string allowing implicit type conversion (use === or !==)'
- @onpush((tok.EQOP, op.EQ))
- def comparison_type_conv(self, node):
- for kid in node.kids:
- if kid.kind == tok.PRIMARY and kid.opcode in (op.NULL, op.TRUE, op.FALSE):
- continue
- if kid.kind == tok.NUMBER and not kid.dval:
- continue
- if kid.kind == tok.STRING and not kid.atom:
- continue
- raise LintWarning, kid
+@lookfor((tok.EQOP, op.EQ))
+def comparison_type_conv(node):
+ for kid in node.kids:
+ if kid.kind == tok.PRIMARY and kid.opcode in (op.NULL, op.TRUE, op.FALSE):
+ continue
+ if kid.kind == tok.NUMBER and not kid.dval:
+ continue
+ if kid.kind == tok.STRING and not kid.atom:
+ continue
+ raise LintWarning, kid
-class default_not_at_end:
- 'the default case is not at the end of the switch statement'
- @onpush(tok.DEFAULT)
- def default_not_at_end(self, node):
- siblings = node.parent.kids
- if node.node_index != len(siblings)-1:
- raise LintWarning, siblings[node.node_index+1]
+@lookfor(tok.DEFAULT)
+def default_not_at_end(node):
+ siblings = node.parent.kids
+ if node.node_index != len(siblings)-1:
+ raise LintWarning, siblings[node.node_index+1]
-class duplicate_case_in_switch:
- 'duplicate case in switch statement'
- @onpush(tok.CASE)
- def duplicate_case_in_switch(self, node):
- # Only look at previous siblings
- siblings = node.parent.kids
- siblings = siblings[:node.node_index]
- # Compare values (first kid)
- node_value = node.kids[0]
- for sibling in siblings:
- if sibling.kind == tok.CASE:
- sibling_value = sibling.kids[0]
- if node_value.is_equivalent(sibling_value, True):
- raise LintWarning, node
+@lookfor(tok.CASE)
+def duplicate_case_in_switch(node):
+ # Only look at previous siblings
+ siblings = node.parent.kids
+ siblings = siblings[:node.node_index]
+ # Compare values (first kid)
+ node_value = node.kids[0]
+ for sibling in siblings:
+ if sibling.kind == tok.CASE:
+ sibling_value = sibling.kids[0]
+ if node_value.is_equivalent(sibling_value, True):
+ raise LintWarning, node
-class missing_default_case:
- 'missing default case in switch statement'
- @onpush(tok.SWITCH)
- def missing_default_case(self, node):
- value, cases = node.kids
- for case in cases.kids:
- if case.kind == tok.DEFAULT:
- return
- raise LintWarning, node
+@lookfor(tok.SWITCH)
+def missing_default_case(node):
+ value, cases = node.kids
+ for case in cases.kids:
+ if case.kind == tok.DEFAULT:
+ return
+ raise LintWarning, node
-class with_statement:
- 'with statement hides undeclared variables; use temporary variable instead'
- @onpush(tok.WITH)
- def with_statement(self, node):
+@lookfor(tok.WITH)
+def with_statement(node):
+ raise LintWarning, node
+
+@lookfor(tok.EQOP,tok.RELOP)
+def useless_comparison(node):
+ lvalue, rvalue = node.kids
+ if lvalue.is_equivalent(rvalue):
raise LintWarning, node
-class useless_comparison:
- 'useless comparison; comparing identical expressions'
- @onpush(tok.EQOP,tok.RELOP)
- def useless_comparison(self, node):
- lvalue, rvalue = node.kids
- if lvalue.is_equivalent(rvalue):
- raise LintWarning, node
+@lookfor((tok.COLON, op.NAME))
+def use_of_label(node):
+ raise LintWarning, node
-class use_of_label:
- 'use of label'
- @onpush((tok.COLON, op.NAME))
- def use_of_label(self, node):
+@lookfor(tok.LC)
+def meaningless_block(node):
+ if node.parent and node.parent.kind == tok.LC:
raise LintWarning, node
-class meaningless_block:
- 'meaningless block; curly braces have no impact'
- @onpush(tok.LC)
- def meaningless_block(self, node):
- if node.parent and node.parent.kind == tok.LC:
- raise LintWarning, node
+@lookfor((tok.OBJECT, op.REGEXP))
+def misplaced_regex(node):
+ if node.parent.kind == tok.NAME and node.parent.opcode == op.SETNAME:
+ return # Allow in var statements
+ if node.parent.kind == tok.ASSIGN and node.parent.opcode == op.NOP:
+ return # Allow in assigns
+ if node.parent.kind == tok.COLON and node.parent.parent.kind == tok.RC:
+ return # Allow in object literals
+ if node.parent.kind == tok.LP and node.parent.opcode == op.CALL:
+ return # Allow in parameters
+ if node.parent.kind == tok.DOT and node.parent.opcode == op.GETPROP:
+ return # Allow in /re/.property
+ if node.parent.kind == tok.RETURN:
+ return # Allow for return values
+ raise LintWarning, node
-class misplaced_regex:
- 'regular expressions should be preceded by a left parenthesis, assignment, colon, or comma'
- @onpush((tok.OBJECT, op.REGEXP))
- def misplaced_regex(self, node):
- if node.parent.kind == tok.NAME and node.parent.opcode == op.SETNAME:
- return # Allow in var statements
- if node.parent.kind == tok.ASSIGN and node.parent.opcode == op.NOP:
- return # Allow in assigns
- if node.parent.kind == tok.COLON and node.parent.parent.kind == tok.RC:
- return # Allow in object literals
- if node.parent.kind == tok.LP and node.parent.opcode == op.CALL:
- return # Allow in parameters
- if node.parent.kind == tok.DOT and node.parent.opcode == op.GETPROP:
- return # Allow in /re/.property
- if node.parent.kind == tok.RETURN:
- return # Allow for return values
+@lookfor(tok.ASSIGN)
+def assign_to_function_call(node):
+ if node.kids[0].kind == tok.LP:
raise LintWarning, node
-class assign_to_function_call:
- 'assignment to a function call'
- @onpush(tok.ASSIGN)
- def assign_to_function_call(self, node):
- if node.kids[0].kind == tok.LP:
- raise LintWarning, node
+@lookfor(tok.IF)
+def ambiguous_else_stmt(node):
+ # Only examine this node if it has an else statement.
+ condition, if_, else_ = node.kids
+ if not else_:
+ return
-class ambiguous_else_stmt:
- 'the else statement could be matched with one of multiple if statements (use curly braces to indicate intent'
- @onpush(tok.IF)
- def ambiguous_else_stmt(self, node):
- # Only examine this node if it has an else statement.
- condition, if_, else_ = node.kids
- if not else_:
+ tmp = node
+ while tmp:
+ # Curly braces always clarify if statements.
+ if tmp.kind == tok.LC:
return
+ # Else is only ambiguous in the first branch of an if statement.
+ if tmp.parent.kind == tok.IF and tmp.node_index == 1:
+ raise LintWarning, else_
+ tmp = tmp.parent
- tmp = node
- while tmp:
- # Curly braces always clarify if statements.
- if tmp.kind == tok.LC:
- return
- # Else is only ambiguous in the first branch of an if statement.
- if tmp.parent.kind == tok.IF and tmp.node_index == 1:
- raise LintWarning, else_
- tmp = tmp.parent
+@lookfor(tok.IF, tok.WHILE, tok.DO, tok.FOR, tok.WITH)
+def block_without_braces(node):
+ if node.kids[1].kind != tok.LC:
+ raise LintWarning, node.kids[1]
-class block_without_braces:
- 'block statement without curly braces'
- @onpush(tok.IF, tok.WHILE, tok.DO, tok.FOR, tok.WITH)
- def block_without_braces(self, node):
- if node.kids[1].kind != tok.LC:
- raise LintWarning, node.kids[1]
+_block_nodes = (tok.IF, tok.WHILE, tok.DO, tok.FOR, tok.WITH)
+@lookfor(*_block_nodes)
+def ambiguous_nested_stmt(node):
+ # Ignore "else if"
+ if node.kind == tok.IF and node.node_index == 2 and node.parent.kind == tok.IF:
+ return
-class ambiguous_nested_stmt:
- 'block statements containing block statements should use curly braces to resolve ambiguity'
- _block_nodes = (tok.IF, tok.WHILE, tok.DO, tok.FOR, tok.WITH)
- @onpush(*_block_nodes)
- def ambiguous_nested_stmt(self, node):
- # Ignore "else if"
- if node.kind == tok.IF and node.node_index == 2 and node.parent.kind == tok.IF:
- return
+ # If the parent is a block, it means a block statement
+ # was inside a block statement without clarifying curlies.
+ # (Otherwise, the node type would be tok.LC.)
+ if node.parent.kind in _block_nodes:
+ raise LintWarning, node
- # If the parent is a block, it means a block statement
- # was inside a block statement without clarifying curlies.
- # (Otherwise, the node type would be tok.LC.)
- if node.parent.kind in self._block_nodes:
- raise LintWarning, node
+@lookfor(tok.INC, tok.DEC)
+def inc_dec_within_stmt(node):
+ if node.parent.kind == tok.SEMI:
+ return
-class inc_dec_within_stmt:
- 'increment (++) and decrement (--) operators used as part of greater statement'
- @onpush(tok.INC, tok.DEC)
- def inc_dec_within_stmt(self, node):
- if node.parent.kind == tok.SEMI:
- return
+ # Allow within the third part of the "for"
+ tmp = node
+ while tmp and tmp.parent and tmp.parent.kind == tok.COMMA:
+ tmp = tmp.parent
+ if tmp and tmp.node_index == 2 and \
+ tmp.parent.kind == tok.RESERVED and \
+ tmp.parent.parent.kind == tok.FOR:
+ return
- # Allow within the third part of the "for"
- tmp = node
- while tmp and tmp.parent and tmp.parent.kind == tok.COMMA:
- tmp = tmp.parent
- if tmp and tmp.node_index == 2 and \
- tmp.parent.kind == tok.RESERVED and \
- tmp.parent.parent.kind == tok.FOR:
- return
+ raise LintWarning, node
+@lookfor(tok.COMMA)
+def comma_separated_stmts(node):
+ # Allow within the first and third part of "for(;;)"
+ if _get_branch_in_for(node) in (0, 2):
+ return
+ # This is an array
+ if node.parent.kind == tok.RB:
+ return
+ raise LintWarning, node
+
+@lookfor(tok.SEMI)
+def empty_statement(node):
+ if not node.kids[0]:
raise LintWarning, node
- def _is_for_ternary_stmt(self, node, branch=None):
- if node.parent and node.parent.kind == tok.COMMA:
- return _is_for_ternary_stmt(node.parent, branch)
- return node.node_index == branch and \
- node.parent and \
- node.parent.kind == tok.RESERVED and \
- node.parent.parent.kind == tok.FOR
+@lookfor(tok.LC)
+def empty_statement_(node):
+ if node.kids:
+ return
+ # Ignore the outermost block.
+ if not node.parent:
+ return
+ # Some empty blocks are meaningful.
+ if node.parent.kind in (tok.CATCH, tok.CASE, tok.DEFAULT, tok.SWITCH, tok.FUNCTION):
+ return
+ raise LintWarning, node
-class comma_separated_stmts:
- 'multiple statements separated by commas (use semicolons?)'
- @onpush(tok.COMMA)
- def comma_separated_stmts(self, node):
- # Allow within the first and third part of "for(;;)"
- if _get_branch_in_for(node) in (0, 2):
- return
- # This is an array
- if node.parent.kind == tok.RB:
- return
+@lookfor(tok.CASE, tok.DEFAULT)
+def missing_break(node):
+ # The last item is handled separately
+ if node.node_index == len(node.parent.kids)-1:
+ return
+ case_contents = node.kids[1]
+ assert case_contents.kind == tok.LC
+ # Ignore empty case statements
+ if not case_contents.kids:
+ return
+ if None in _get_exit_points(case_contents):
+ # Show the warning on the *next* node.
+ raise LintWarning, node.parent.kids[node.node_index+1]
+
+@lookfor(tok.CASE, tok.DEFAULT)
+def missing_break_for_last_case(node):
+ if node.node_index < len(node.parent.kids)-1:
+ return
+ case_contents = node.kids[1]
+ assert case_contents.kind == tok.LC
+ if None in _get_exit_points(case_contents):
raise LintWarning, node
-class empty_statement:
- 'empty statement or extra semicolon'
- @onpush(tok.SEMI)
- def empty_statement(self, node):
- if not node.kids[0]:
- raise LintWarning, node
- @onpush(tok.LC)
- def empty_statement_(self, node):
- if node.kids:
- return
- # Ignore the outermost block.
- if not node.parent:
- return
- # Some empty blocks are meaningful.
- if node.parent.kind in (tok.CATCH, tok.CASE, tok.DEFAULT, tok.SWITCH, tok.FUNCTION):
- return
+@lookfor(tok.INC)
+def multiple_plus_minus(node):
+ if node.node_index == 0 and node.parent.kind == tok.PLUS:
raise LintWarning, node
+@lookfor(tok.DEC)
+def multiple_plus_minus_(node):
+ if node.node_index == 0 and node.parent.kind == tok.MINUS:
+ raise LintWarning, node
-class missing_break:
- 'missing break statement'
- @onpush(tok.CASE, tok.DEFAULT)
- def missing_break(self, node):
- # The last item is handled separately
- if node.node_index == len(node.parent.kids)-1:
- return
- case_contents = node.kids[1]
- assert case_contents.kind == tok.LC
- # Ignore empty case statements
- if not case_contents.kids:
- return
- if None in _get_exit_points(case_contents):
- # Show the warning on the *next* node.
- raise LintWarning, node.parent.kids[node.node_index+1]
+@lookfor((tok.NAME, op.SETNAME))
+def useless_assign(node):
+ if node.parent.kind == tok.ASSIGN:
+ assert node.node_index == 0
+ value = node.parent.kids[1]
+ elif node.parent.kind == tok.VAR:
+ value = node.kids[0]
+ if value and value.kind == tok.NAME and node.atom == value.atom:
+ raise LintWarning, node
-class missing_break_for_last_case:
- 'missing break statement for last case in switch'
- @onpush(tok.CASE, tok.DEFAULT)
- def missing_break_for_last_case(self, node):
- if node.node_index < len(node.parent.kids)-1:
- return
- case_contents = node.kids[1]
- assert case_contents.kind == tok.LC
- if None in _get_exit_points(case_contents):
- raise LintWarning, node
+@lookfor(tok.BREAK, tok.CONTINUE, tok.RETURN, tok.THROW)
+def unreachable_code(node):
+ if node.parent.kind == tok.LC and \
+ node.node_index != len(node.parent.kids)-1:
+ raise LintWarning, node.parent.kids[node.node_index+1]
-class multiple_plus_minus:
- 'unknown order of operations for successive plus (e.g. x+++y) or minus (e.g. x---y) signs'
- @onpush(tok.INC)
- def multiple_plus_minus(self, node):
- if node.node_index == 0 and node.parent.kind == tok.PLUS:
- raise LintWarning, node
- @onpush(tok.DEC)
- def multiple_plus_minus_(self, node):
- if node.node_index == 0 and node.parent.kind == tok.MINUS:
- raise LintWarning, node
+#TODO: @lookfor(tok.IF)
+def meaningless_block(node):
+ condition, if_, else_ = node.kids
+ if condition.kind == tok.PRIMARY and condition.opcode in (op.TRUE, op.FALSE, op.NULL):
+ raise LintWarning, condition
+#TODO: @lookfor(tok.WHILE)
+def meaningless_blocK_(node):
+ condition = node.kids[0]
+ if condition.kind == tok.PRIMARY and condition.opcode in (op.FALSE, op.NULL):
+ raise LintWarning, condition
+@lookfor(tok.LC)
+def meaningless_block__(node):
+ if node.parent and node.parent.kind == tok.LC:
+ raise LintWarning, node
-class useless_assign:
- 'useless assignment'
- @onpush((tok.NAME, op.SETNAME))
- def useless_assign(self, node):
- if node.parent.kind == tok.ASSIGN:
- assert node.node_index == 0
- value = node.parent.kids[1]
- elif node.parent.kind == tok.VAR:
- value = node.kids[0]
- if value and value.kind == tok.NAME and node.atom == value.atom:
- raise LintWarning, node
+@lookfor((tok.UNARYOP, op.VOID))
+def useless_void(node):
+ raise LintWarning, node
-class unreachable_code:
- 'unreachable code'
- @onpush(tok.BREAK, tok.CONTINUE, tok.RETURN, tok.THROW)
- def unreachable_code(self, node):
- if node.parent.kind == tok.LC and \
- node.node_index != len(node.parent.kids)-1:
- raise LintWarning, node.parent.kids[node.node_index+1]
+@lookfor((tok.LP, op.CALL))
+def parseint_missing_radix(node):
+ if node.kids[0].kind == tok.NAME and node.kids[0].atom == 'parseInt' and len(node.kids) <= 2:
+ raise LintWarning, node
-class meaningless_block:
- 'meaningless block; curly braces have no impact'
- #TODO: @onpush(tok.IF)
- def meaningless_block(self, node):
- condition, if_, else_ = node.kids
- if condition.kind == tok.PRIMARY and condition.opcode in (op.TRUE, op.FALSE, op.NULL):
- raise LintWarning, condition
- #TODO: @onpush(tok.WHILE)
- def meaningless_blocK_(self, node):
- condition = node.kids[0]
- if condition.kind == tok.PRIMARY and condition.opcode in (op.FALSE, op.NULL):
- raise LintWarning, condition
- @onpush(tok.LC)
- def meaningless_block__(self, node):
- if node.parent and node.parent.kind == tok.LC:
- raise LintWarning, node
+@lookfor(tok.NUMBER)
+def leading_decimal_point(node):
+ if node.atom.startswith('.'):
+ raise LintWarning, node
-class useless_void:
- 'use of the void type may be unnecessary (void is always undefined)'
- @onpush((tok.UNARYOP, op.VOID))
- def useless_void(self, node):
+@lookfor(tok.NUMBER)
+def trailing_decimal_point(node):
+ if node.parent.kind == tok.DOT:
raise LintWarning, node
+ if node.atom.endswith('.'):
+ raise LintWarning, node
-class parseint_missing_radix:
- 'parseInt missing radix parameter'
- @onpush((tok.LP, op.CALL))
- def parseint_missing_radix(self, node):
- if node.kids[0].kind == tok.NAME and node.kids[0].atom == 'parseInt' and len(node.kids) <= 2:
- raise LintWarning, node
+_octal_regexp = re.compile('^0[0-9]')
+@lookfor(tok.NUMBER)
+def octal_number(node):
+ if _octal_regexp.match(node.atom):
+ raise LintWarning, node
-class leading_decimal_point:
- 'leading decimal point may indicate a number or an object member'
- @onpush(tok.NUMBER)
- def leading_decimal_point(self, node):
- if node.atom.startswith('.'):
- raise LintWarning, node
+@lookfor(tok.RB)
+def trailing_comma_in_array(node):
+ if node.end_comma:
+ raise LintWarning, node
-class trailing_decimal_point:
- 'trailing decimal point may indicate a number or an object member'
- @onpush(tok.NUMBER)
- def trailing_decimal_point(self, node):
- if node.parent.kind == tok.DOT:
- raise LintWarning, node
- if node.atom.endswith('.'):
- raise LintWarning, node
+@lookfor(tok.STRING)
+def useless_quotes(node):
+ if node.node_index == 0 and node.parent.kind == tok.COLON:
+ raise LintWarning, node
-class octal_number:
- 'leading zeros make an octal number'
- _regexp = re.compile('^0[0-9]')
- @onpush(tok.NUMBER)
- def octal_number(self, node):
- if self._regexp.match(node.atom):
- raise LintWarning, node
-
-class trailing_comma_in_array:
- 'extra comma is not recommended in array initializers'
- @onpush(tok.RB)
- def trailing_comma_in_array(self, node):
- if node.end_comma:
- raise LintWarning, node
-
-class useless_quotes:
- 'the quotation marks are unnecessary'
- @onpush(tok.STRING)
- def useless_quotes(self, node):
- if node.node_index == 0 and node.parent.kind == tok.COLON:
- raise LintWarning, node
-
-class mismatch_ctrl_comments:
- 'mismatched control comment; "ignore" and "end" control comments must have a one-to-one correspondence'
+@lookfor()
+def mismatch_ctrl_comments(node):
pass
-class redeclared_var:
- 'redeclaration of {0} {1}'
+@lookfor()
+def redeclared_var(node):
pass
-class undeclared_identifier:
- 'undeclared identifier: {0}'
+@lookfor()
+def undeclared_identifier(node):
pass
-class jsl_cc_not_understood:
- 'couldn\'t understand control comment using /*jsl:keyword*/ syntax'
+@lookfor()
+def jsl_cc_not_understood(node):
pass
-class nested_comment:
- 'nested comment'
+@lookfor()
+def nested_comment(node):
pass
-class legacy_cc_not_understood:
- 'couldn\'t understand control comment using /*@keyword@*/ syntax'
+@lookfor()
+def legacy_cc_not_understood(node):
pass
-class var_hides_arg:
- 'variable {0} hides argument'
+@lookfor()
+def var_hides_arg(node):
pass
-class duplicate_formal:
- 'TODO'
+@lookfor()
+def duplicate_formal(node):
pass
-class missing_semicolon:
- 'missing semicolon'
+@lookfor()
+def missing_semicolon(node):
pass
-class ambiguous_newline:
- 'unexpected end of line; it is ambiguous whether these lines are part of the same statement'
+@lookfor()
+def ambiguous_newline(node):
pass
-class missing_option_explicit:
- 'the "option explicit" control comment is missing'
+@lookfor()
+def missing_option_explicit(node):
pass
-class partial_option_explicit:
- 'the "option explicit" control comment, if used, must be in the first script tag'
+@lookfor()
+def partial_option_explicit(node):
pass
-class dup_option_explicit:
- 'duplicate "option explicit" control comment'
+@lookfor()
+def dup_option_explicit(node):
pass
-klasses = tuple([
- obj for
- obj in
- sys.modules[__name__].__dict__.values() if
- type(obj) == types.ClassType
-])
+def make_visitors():
+ functions = [
+ obj for obj in sys.modules[__name__].__dict__.values()
+ if type(obj) == types.FunctionType and hasattr(obj, '_lint_nodes')
+ ]
+ visitors = {}
+ for func in functions:
+ for node_kind in func._lint_nodes:
+ try:
+ visitors[node_kind].append(func)
+ except KeyError:
+ visitors[node_kind] = [func]
+ return visitors
+
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|