[javascriptlint-commit] SF.net SVN: javascriptlint: [195] trunk/pyjsl
Status: Beta
Brought to you by:
matthiasmiller
|
From: <mat...@us...> - 2008-04-25 22:24:52
|
Revision: 195
http://javascriptlint.svn.sourceforge.net/javascriptlint/?rev=195&view=rev
Author: matthiasmiller
Date: 2008-04-25 15:24:51 -0700 (Fri, 25 Apr 2008)
Log Message:
-----------
Change scope checks to use visitors.
Modified Paths:
--------------
trunk/pyjsl/lint.py
trunk/pyjsl/visitation.py
Modified: trunk/pyjsl/lint.py
===================================================================
--- trunk/pyjsl/lint.py 2008-04-25 21:52:35 UTC (rev 194)
+++ trunk/pyjsl/lint.py 2008-04-25 22:24:51 UTC (rev 195)
@@ -217,14 +217,22 @@
for pos, msg in parse_errors:
_report(pos, msg, False)
- visitors = visitation.make_visitors(warnings.klasses)['push']
+ # Find all visitors and convert them into "onpush" callbacks that call "report"
+ visitors = {}
+ visitation.make_visitors(visitors, warnings.klasses)
+ for event in visitors:
+ for kind, callbacks in visitors[event].items():
+ visitors[event][kind] = [_getreporter(callback, report) for callback in callbacks]
assert not script_cache
imports = script_cache['imports'] = set()
scope = script_cache['scope'] = Scope(root)
+ # Push the scope/variable checks.
+ visitation.make_visitors(visitors, [_get_scope_checks(scope, report)])
+
# kickoff!
- _lint_node(root, visitors, report, scope)
+ _lint_node(root, visitors)
# Process imports by copying global declarations into the universal scope.
imports |= set(conf['declarations'])
@@ -245,6 +253,15 @@
if not node.atom in imports:
report(node, 'undeclared_identifier')
+def _getreporter(visitor, report):
+ def onpush(node):
+ try:
+ 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__)
+ return onpush
+
def _warn_or_declare(scope, name, node, report):
other = scope.get_identifier(name)
if other and other.kind == tok.FUNCTION and name in other.fn_args:
@@ -254,42 +271,58 @@
else:
scope.add_declaration(name, node)
-def _lint_node(node, visitors, report, scope):
+def _get_scope_checks(scope, report):
+ scopes = [scope]
- # Let the visitors warn.
- for kind in (node.kind, (node.kind, node.opcode)):
- if kind in visitors:
- for visitor in visitors[kind]:
- try:
- 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__)
+ class scope_checks:
+ ' '
+ @visitation.visit('push', tok.NAME)
+ def _name(self, node):
+ if node.node_index == 0 and node.parent.kind == tok.COLON and node.parent.parent.kind == tok.RC:
+ pass # left side of object literal
+ elif node.parent.kind == tok.CATCH:
+ scopes[-1].add_declaration(node.atom, node)
+ else:
+ scopes[-1].add_reference(node.atom, node)
- if node.kind == tok.NAME:
- if node.node_index == 0 and node.parent.kind == tok.COLON and node.parent.parent.kind == tok.RC:
- pass # left side of object literal
- elif node.parent.kind == tok.CATCH:
- scope.add_declaration(node.atom, node)
- else:
- scope.add_reference(node.atom, node)
+ @visitation.visit('push', tok.FUNCTION)
+ def _push_func(self, node):
+ if node.fn_name:
+ _warn_or_declare(scopes[-1], node.fn_name, node, report)
+ self._push_scope(node)
+ for var_name in node.fn_args:
+ scopes[-1].add_declaration(var_name, node)
- # Push function identifiers
- if node.kind == tok.FUNCTION:
- if node.fn_name:
- _warn_or_declare(scope, node.fn_name, node, report)
- scope = scope.add_scope(node)
- for var_name in node.fn_args:
- scope.add_declaration(var_name, node)
- elif node.kind == tok.LEXICALSCOPE:
- scope = scope.add_scope(node)
- elif node.kind == tok.WITH:
- scope = scope.add_scope(node)
+ @visitation.visit('push', tok.LEXICALSCOPE, tok.WITH)
+ def _push_scope(self, node):
+ scopes.append(scopes[-1].add_scope(node))
- if node.parent and node.parent.kind == tok.VAR:
- _warn_or_declare(scope, node.atom, node, report)
+ @visitation.visit('pop', tok.FUNCTION, tok.LEXICALSCOPE, tok.WITH)
+ def _pop_scope(self, node):
+ scopes.pop()
+ @visitation.visit('push', tok.VAR)
+ def _push_var(self, node):
+ for kid in node.kids:
+ _warn_or_declare(scope, kid.atom, node, report)
+
+ return scope_checks
+
+
+def _lint_node(node, visitors):
+
+ for kind in (node.kind, (node.kind, node.opcode)):
+ if kind in visitors['push']:
+ for visitor in visitors['push'][kind]:
+ visitor(node)
+
for child in node.kids:
if child:
- _lint_node(child, visitors, report, scope)
+ _lint_node(child, visitors)
+ for kind in (node.kind, (node.kind, node.opcode)):
+ if kind in visitors['pop']:
+ for visitor in visitors['pop'][kind]:
+ visitor(node)
+
+
Modified: trunk/pyjsl/visitation.py
===================================================================
--- trunk/pyjsl/visitation.py 2008-04-25 21:52:35 UTC (rev 194)
+++ trunk/pyjsl/visitation.py 2008-04-25 22:24:51 UTC (rev 195)
@@ -10,13 +10,21 @@
def _decorate(fn):
fn._visit_event = event
fn._visit_nodes = args
+ print dir(fn), fn.func_name
+ raise ValueError
return fn
return _decorate
-def make_visitors(klasses):
+def make_visitors(visitors, klasses):
""" Searches klasses for all member functions decorated with @visit and
- returns a dictionary that maps from node type to visitor function. """
- visitors = {}
+ fills a dictionary that looks like:
+ visitors = {
+ 'event_name': {
+ 'node_type' : [func1, func2]
+ }
+ }
+ """
+ assert isinstance(visitors, dict)
# Intantiate an instance of each class
for klass in klasses:
@@ -32,13 +40,15 @@
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]
+ try:
+ event_visitors = visitors[func._visit_event]
+ except KeyError:
+ event_visitors = visitors[func._visit_event] = {}
# Map from node_kind to the function
- if not node_kind in visitors:
- event_visitors[node_kind] = []
- event_visitors[node_kind].append(func)
+ try:
+ event_visitors[node_kind].append(func)
+ except KeyError:
+ event_visitors[node_kind] = [func]
return visitors
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|