[javascriptlint-commit] SF.net SVN: javascriptlint: [193] trunk/pyjsl
Status: Beta
Brought to you by:
matthiasmiller
|
From: <mat...@us...> - 2008-04-25 21:39:53
|
Revision: 193
http://javascriptlint.svn.sourceforge.net/javascriptlint/?rev=193&view=rev
Author: matthiasmiller
Date: 2008-04-25 14:39:29 -0700 (Fri, 25 Apr 2008)
Log Message:
-----------
Allow node visitors to specify an event (e.g. "push" vs. "pop").
Modified Paths:
--------------
trunk/pyjsl/lint.py
trunk/pyjsl/visitation.py
trunk/pyjsl/warnings.py
Modified: trunk/pyjsl/lint.py
===================================================================
--- trunk/pyjsl/lint.py 2008-04-25 21:16:20 UTC (rev 192)
+++ trunk/pyjsl/lint.py 2008-04-25 21:39:29 UTC (rev 193)
@@ -217,7 +217,7 @@
for pos, msg in parse_errors:
_report(pos, msg, False)
- visitors = visitation.make_visitors(warnings.klasses)
+ visitors = visitation.make_visitors(warnings.klasses)['push']
assert not script_cache
imports = script_cache['imports'] = set()
Modified: trunk/pyjsl/visitation.py
===================================================================
--- trunk/pyjsl/visitation.py 2008-04-25 21:16:20 UTC (rev 192)
+++ trunk/pyjsl/visitation.py 2008-04-25 21:39:29 UTC (rev 193)
@@ -3,11 +3,12 @@
traverse the tree to generate warnings.
"""
-def visit(*args):
+def visit(event, *args):
""" This decorator is used to indicate which nodes the function should
examine. The function should accept (self, node) and return the relevant
node or None. """
def _decorate(fn):
+ fn._visit_event = event
fn._visit_nodes = args
return fn
return _decorate
@@ -27,10 +28,17 @@
# Look for functions with the "_visit_nodes" property.
visitor = klass()
for func in [getattr(visitor, name) for name in dir(visitor)]:
+ event_visitors = None
for node_kind in getattr(func, '_visit_nodes', ()):
+ # Group visitors by event (e.g. push vs pop)
+ if not event_visitors:
+ if not func._visit_event in visitors:
+ visitors[func._visit_event] = {}
+ event_visitors = visitors[func._visit_event]
+
# Map from node_kind to the function
if not node_kind in visitors:
- visitors[node_kind] = []
- visitors[node_kind].append(func)
+ event_visitors[node_kind] = []
+ event_visitors[node_kind].append(func)
return visitors
Modified: trunk/pyjsl/warnings.py
===================================================================
--- trunk/pyjsl/warnings.py 2008-04-25 21:16:20 UTC (rev 192)
+++ trunk/pyjsl/warnings.py 2008-04-25 21:39:29 UTC (rev 193)
@@ -4,7 +4,7 @@
underscores. Its docstring should be the warning message.
The class can have one more more member functions to inspect nodes. The
-function should be decorated with a @lookat call specifying the nodes it
+function should be decorated with a @onpush 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.
@@ -13,7 +13,7 @@
class warning_name:
'questionable JavaScript coding style'
- @lookat(tok.NODEKIND, (tok.NODEKIND, op.OPCODE))
+ @onpush(tok.NODEKIND, (tok.NODEKIND, op.OPCODE))
def _lint(self, node):
if questionable:
return node
@@ -22,11 +22,14 @@
import sys
import types
-from visitation import visit as lookat
+import visitation
from pyspidermonkey import tok, op
# TODO: document inspect, node:opcode, etc
+def onpush(*args):
+ return visitation.visit('push', *args)
+
def _get_branch_in_for(node):
" Returns None if this is not one of the branches in a 'for' "
if node.parent and node.parent.kind == tok.RESERVED and \
@@ -119,7 +122,7 @@
class comparison_type_conv:
'comparisons against null, 0, true, false, or an empty string allowing implicit type conversion (use === or !==)'
- @lookat((tok.EQOP, op.EQ))
+ @onpush((tok.EQOP, op.EQ))
def _lint(self, node):
lvalue, rvalue = node.kids
if not self._allow_coercive_compare(lvalue) or \
@@ -136,7 +139,7 @@
class default_not_at_end:
'the default case is not at the end of the switch statement'
- @lookat(tok.DEFAULT)
+ @onpush(tok.DEFAULT)
def _lint(self, node):
siblings = node.parent.kids
if node.node_index != len(siblings)-1:
@@ -144,7 +147,7 @@
class duplicate_case_in_switch:
'duplicate case in switch statement'
- @lookat(tok.CASE)
+ @onpush(tok.CASE)
def _lint(self, node):
# Only look at previous siblings
siblings = node.parent.kids
@@ -159,7 +162,7 @@
class missing_default_case:
'missing default case in switch statement'
- @lookat(tok.SWITCH)
+ @onpush(tok.SWITCH)
def _lint(self, node):
value, cases = node.kids
for case in cases.kids:
@@ -169,13 +172,13 @@
class with_statement:
'with statement hides undeclared variables; use temporary variable instead'
- @lookat(tok.WITH)
+ @onpush(tok.WITH)
def _lint(self, node):
return node
class useless_comparison:
'useless comparison; comparing identical expressions'
- @lookat(tok.EQOP,tok.RELOP)
+ @onpush(tok.EQOP,tok.RELOP)
def _lint(self, node):
lvalue, rvalue = node.kids
if lvalue.is_equivalent(rvalue):
@@ -183,20 +186,20 @@
class use_of_label:
'use of label'
- @lookat((tok.COLON, op.NAME))
+ @onpush((tok.COLON, op.NAME))
def _lint(self, node):
return node
class meaningless_block:
'meaningless block; curly braces have no impact'
- @lookat(tok.LC)
+ @onpush(tok.LC)
def _lint(self, node):
if node.parent and node.parent.kind == tok.LC:
return node
class misplaced_regex:
'regular expressions should be preceded by a left parenthesis, assignment, colon, or comma'
- @lookat((tok.OBJECT, op.REGEXP))
+ @onpush((tok.OBJECT, op.REGEXP))
def _lint(self, node):
if node.parent.kind == tok.NAME and node.parent.opcode == op.SETNAME:
return # Allow in var statements
@@ -214,14 +217,14 @@
class assign_to_function_call:
'assignment to a function call'
- @lookat(tok.ASSIGN)
+ @onpush(tok.ASSIGN)
def _lint(self, node):
if node.kids[0].kind == tok.LP:
return node
class ambiguous_else_stmt:
'the else statement could be matched with one of multiple if statements (use curly braces to indicate intent'
- @lookat(tok.IF)
+ @onpush(tok.IF)
def _lint(self, node):
# Only examine this node if it has an else statement.
condition, if_, else_ = node.kids
@@ -240,7 +243,7 @@
class block_without_braces:
'block statement without curly braces'
- @lookat(tok.IF, tok.WHILE, tok.DO, tok.FOR, tok.WITH)
+ @onpush(tok.IF, tok.WHILE, tok.DO, tok.FOR, tok.WITH)
def _lint(self, node):
if node.kids[1].kind != tok.LC:
return node.kids[1]
@@ -248,7 +251,7 @@
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)
- @lookat(*_block_nodes)
+ @onpush(*_block_nodes)
def _lint(self, node):
# Ignore "else if"
if node.kind == tok.IF and node.node_index == 2 and node.parent.kind == tok.IF:
@@ -262,7 +265,7 @@
class inc_dec_within_stmt:
'increment (++) and decrement (--) operators used as part of greater statement'
- @lookat(tok.INC, tok.DEC)
+ @onpush(tok.INC, tok.DEC)
def _lint(self, node):
if node.parent.kind == tok.SEMI:
return None
@@ -287,7 +290,7 @@
class comma_separated_stmts:
'multiple statements separated by commas (use semicolons?)'
- @lookat(tok.COMMA)
+ @onpush(tok.COMMA)
def _lint(self, node):
# Allow within the first and third part of "for(;;)"
if _get_branch_in_for(node) in (0, 2):
@@ -299,11 +302,11 @@
class empty_statement:
'empty statement or extra semicolon'
- @lookat(tok.SEMI)
+ @onpush(tok.SEMI)
def _semi(self, node):
if not node.kids[0]:
return node
- @lookat(tok.LC)
+ @onpush(tok.LC)
def _lc(self, node):
if node.kids:
return
@@ -317,7 +320,7 @@
class missing_break:
'missing break statement'
- @lookat(tok.CASE, tok.DEFAULT)
+ @onpush(tok.CASE, tok.DEFAULT)
def _lint(self, node):
# The last item is handled separately
if node.node_index == len(node.parent.kids)-1:
@@ -333,7 +336,7 @@
class missing_break_for_last_case:
'missing break statement for last case in switch'
- @lookat(tok.CASE, tok.DEFAULT)
+ @onpush(tok.CASE, tok.DEFAULT)
def _lint(self, node):
if node.node_index < len(node.parent.kids)-1:
return
@@ -344,18 +347,18 @@
class multiple_plus_minus:
'unknown order of operations for successive plus (e.g. x+++y) or minus (e.g. x---y) signs'
- @lookat(tok.INC)
+ @onpush(tok.INC)
def _inc(self, node):
if node.node_index == 0 and node.parent.kind == tok.PLUS:
return node
- @lookat(tok.DEC)
+ @onpush(tok.DEC)
def _dec(self, node):
if node.node_index == 0 and node.parent.kind == tok.MINUS:
return node
class useless_assign:
'useless assignment'
- @lookat((tok.NAME, op.SETNAME))
+ @onpush((tok.NAME, op.SETNAME))
def _lint(self, node):
if node.parent.kind == tok.ASSIGN:
assert node.node_index == 0
@@ -367,7 +370,7 @@
class unreachable_code:
'unreachable code'
- @lookat(tok.BREAK, tok.CONTINUE, tok.RETURN, tok.THROW)
+ @onpush(tok.BREAK, tok.CONTINUE, tok.RETURN, tok.THROW)
def _lint(self, node):
if node.parent.kind == tok.LC and \
node.node_index != len(node.parent.kids)-1:
@@ -375,44 +378,44 @@
class meaningless_block:
'meaningless block; curly braces have no impact'
- #TODO: @lookat(tok.IF)
+ #TODO: @onpush(tok.IF)
def _lint(self, node):
condition, if_, else_ = node.kids
if condition.kind == tok.PRIMARY and condition.opcode in (op.TRUE, op.FALSE, op.NULL):
return condition
- #TODO: @lookat(tok.WHILE)
+ #TODO: @onpush(tok.WHILE)
def _lint(self, node):
condition = node.kids[0]
if condition.kind == tok.PRIMARY and condition.opcode in (op.FALSE, op.NULL):
return condition
- @lookat(tok.LC)
+ @onpush(tok.LC)
def _lint(self, node):
if node.parent and node.parent.kind == tok.LC:
return node
class useless_void:
'use of the void type may be unnecessary (void is always undefined)'
- @lookat((tok.UNARYOP, op.VOID))
+ @onpush((tok.UNARYOP, op.VOID))
def _lint(self, node):
return node
class parseint_missing_radix:
'parseInt missing radix parameter'
- @lookat((tok.LP, op.CALL))
+ @onpush((tok.LP, op.CALL))
def _lint(self, node):
if node.kids[0].kind == tok.NAME and node.kids[0].atom == 'parseInt' and len(node.kids) <= 2:
return node
class leading_decimal_point:
'leading decimal point may indicate a number or an object member'
- @lookat(tok.NUMBER)
+ @onpush(tok.NUMBER)
def _lint(self, node):
if node.atom.startswith('.'):
return node
class trailing_decimal_point:
'trailing decimal point may indicate a number or an object member'
- @lookat(tok.NUMBER)
+ @onpush(tok.NUMBER)
def _lint(self, node):
if node.parent.kind == tok.DOT:
return node
@@ -422,21 +425,21 @@
class octal_number:
'leading zeros make an octal number'
_regexp = re.compile('^0[0-9]')
- @lookat(tok.NUMBER)
+ @onpush(tok.NUMBER)
def _line(self, node):
if self._regexp.match(node.atom):
return node
class trailing_comma_in_array:
'extra comma is not recommended in array initializers'
- @lookat(tok.RB)
+ @onpush(tok.RB)
def _line(self, node):
if node.end_comma:
return node
class useless_quotes:
'the quotation marks are unnecessary'
- @lookat(tok.STRING)
+ @onpush(tok.STRING)
def _lint(self, node):
if node.node_index == 0 and node.parent.kind == tok.COLON:
return node
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|