[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. |