[javascriptlint-commit] SF.net SVN: javascriptlint:[232] trunk
Status: Beta
Brought to you by:
matthiasmiller
From: <mat...@us...> - 2008-08-28 04:58:31
|
Revision: 232 http://javascriptlint.svn.sourceforge.net/javascriptlint/?rev=232&view=rev Author: matthiasmiller Date: 2008-08-28 04:58:29 +0000 (Thu, 28 Aug 2008) Log Message: ----------- a rough cut at supporting HTML files Modified Paths: -------------- trunk/jsl.py trunk/pyjsl/lint.py Added Paths: ----------- trunk/tests/html/include.ecmascript trunk/tests/html/include.html Modified: trunk/jsl.py =================================================================== --- trunk/jsl.py 2008-08-28 04:34:11 UTC (rev 231) +++ trunk/jsl.py 2008-08-28 04:58:29 UTC (rev 232) @@ -42,9 +42,8 @@ def run_tests(): for file in get_test_files(): - if file.endswith('.htm') or file.endswith('.html'): - continue #TODO - elif file.endswith('.js'): + ext = os.path.splitext(file)[1] + if ext in ('.htm', '.html', '.js'): try: test.run(file) except test.TestError, error: Modified: trunk/pyjsl/lint.py =================================================================== --- trunk/pyjsl/lint.py 2008-08-28 04:34:11 UTC (rev 231) +++ trunk/pyjsl/lint.py 2008-08-28 04:58:29 UTC (rev 232) @@ -4,6 +4,7 @@ import re import conf +import htmlparse import jsparse import visitation import warnings @@ -177,27 +178,72 @@ node.end_pos() <= self._node.end_pos()): return self +class _Script: + def __init__(self): + self._imports = set() + self.scope = Scope() + def importscript(self, script): + self._imports.add(script) + def hasglobal(self, name): + return not self._findglobal(name, set()) is None + def _findglobal(self, name, searched): + """ searched is a set of all searched scripts """ + # Avoid recursion. + if self in searched: + return + + # Check this scope. + if self.scope.get_identifier(name): + return self + searched.add(self) + + # Search imported scopes. + for script in self._imports: + global_ = script._findglobal(name, searched) + if global_: + return global_ + def lint_files(paths, lint_error, conf=conf.Conf()): - def lint_file(path): + def lint_file(path, kind): def import_script(import_path): import_path = os.path.join(os.path.dirname(path), import_path) - return lint_file(import_path) + return lint_file(import_path, 'js') def _lint_error(*args): return lint_error(normpath, *args) normpath = util.normpath(path) - if not normpath in lint_cache: - lint_cache[normpath] = {} - script = util.readfile(path) - print normpath - _lint_script(script, lint_cache[normpath], _lint_error, conf, import_script) + if normpath in lint_cache: + return lint_cache[normpath] + print normpath + contents = util.readfile(path) + lint_cache[normpath] = _Script() + + script_parts = [] + if kind == 'js': + script_parts.append((None, contents)) + elif kind == 'html': + for script in htmlparse.findscripts(contents): + if script['src']: + other = import_script(script['src']) + lint_cache[normpath].importscript(other) + if script['script'].strip(): + script_parts.append((script['startpos'], script['script'])) + else: + assert False, 'Unsupported file kind: %s' % kind + + _lint_script_parts(script_parts, lint_cache[normpath], _lint_error, conf, import_script) return lint_cache[normpath] lint_cache = {} for path in paths: - lint_file(path) + ext = os.path.splitext(path)[1] + if ext.lower() in ['.htm', '.html']: + lint_file(path, 'html') + else: + lint_file(path, 'js') -def _lint_script(script, script_cache, lint_error, conf, import_callback): +def _lint_script_part(scriptpos, script, script_cache, conf, ignores, + report_native, report_lint, import_callback): def parse_error(row, col, msg): if not msg in ('anon_no_return_value', 'no_return_value', 'redeclared_var', 'var_hides_arg'): @@ -234,42 +280,22 @@ fallthrus.remove(fallthru) return - _report(node.start_pos(), errname, True) + report_lint(node, errname) - def _report(pos, errname, require_key): - try: - if not conf[errname]: - return - except KeyError, err: - if require_key: - raise - - for start, end in ignores: - if pos >= start and pos <= end: - return - - return lint_error(pos.line, pos.col, errname) - parse_errors = [] - ignores = [] declares = [] import_paths = [] fallthrus = [] passes = [] - root = jsparse.parse(script, parse_error) + root = jsparse.parse(script, parse_error, scriptpos) if not root: - # Cache empty results for this script. - assert not script_cache - script_cache['imports'] = set() - script_cache['scope'] = Scope() - # Report errors and quit. for pos, msg in parse_errors: - _report(pos, msg, False) + report_native(pos, msg) return - comments = jsparse.parsecomments(script, root) + comments = jsparse.parsecomments(script, root, scriptpos) start_ignore = None for comment in comments: cc = _parse_control_comment(comment) @@ -313,7 +339,7 @@ # Wait to report parse errors until loading jsl:ignore directives. for pos, msg in parse_errors: - _report(pos, msg, False) + report_native(pos, msg) # Find all visitors and convert them into "onpush" callbacks that call "report" visitors = { @@ -323,12 +349,8 @@ 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() - # Push the scope/variable checks. - visitation.make_visitors(visitors, [_get_scope_checks(scope, report)]) + visitation.make_visitors(visitors, [_get_scope_checks(script_cache.scope, report)]) # kickoff! _lint_node(root, visitors) @@ -339,28 +361,55 @@ report(fallthru, 'invalid_pass') # Process imports by copying global declarations into the universal scope. - imports |= set(conf['declarations']) - imports |= _globals for path in import_paths: - cache = import_callback(path) - imports |= cache['imports'] - imports |= set(cache['scope'].get_identifiers()) + script_cache.importscript(import_callback(path)) for name, node in declares: - declare_scope = scope.find_scope(node) + declare_scope = script_cache.scope.find_scope(node) if declare_scope.get_identifier(name): report(node, 'redeclared_var') else: declare_scope.add_declaration(name, node) +def _lint_script_parts(script_parts, script_cache, lint_error, conf, import_callback): + def report_lint(node, errname): + _report(node.start_pos(), errname, True) + + def report_native(pos, errname): + _report(pos, errname, False) + + def _report(pos, errname, require_key): + try: + if not conf[errname]: + return + except KeyError, err: + if require_key: + raise + + for start, end in ignores: + if pos >= start and pos <= end: + return + + return lint_error(pos.line, pos.col, errname) + + for scriptpos, script in script_parts: + ignores = [] + _lint_script_part(scriptpos, script, script_cache, conf, ignores, + report_native, report_lint, import_callback) + + scope = script_cache.scope unreferenced, undeclared = scope.get_unreferenced_and_undeclared_identifiers() for decl_scope, name, node in undeclared: - if not name in imports: - report(node, 'undeclared_identifier') + if name in conf['declarations']: + continue + if name in _globals: + continue + if not script_cache.hasglobal(name): + report_lint(node, 'undeclared_identifier') for ref_scope, name, node in unreferenced: # Ignore the outer scope. if ref_scope != scope: - report(node, 'unreferenced_identifier') + report_lint(node, 'unreferenced_identifier') def _getreporter(visitor, report): def onpush(node): Added: trunk/tests/html/include.ecmascript =================================================================== --- trunk/tests/html/include.ecmascript (rev 0) +++ trunk/tests/html/include.ecmascript 2008-08-28 04:58:29 UTC (rev 232) @@ -0,0 +1,10 @@ +var global_var = 42; +function GlobalFromInclude() { + var value; + this.set = function(newvalue) { + value = newvalue; + }; + this.get = function() { + return value; + }; +} Added: trunk/tests/html/include.html =================================================================== --- trunk/tests/html/include.html (rev 0) +++ trunk/tests/html/include.html 2008-08-28 04:58:29 UTC (rev 232) @@ -0,0 +1,21 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN"> +<html> +<head> + <title>JavaScript Lint Test Page</title> + <script src="include.ecmascript"></script> + <script type="text/javascript"><!-- + var myglobal = GlobalFromInclude(); + myglobal.set(global_var); + bogus = myglobal.get(); /*warning:undeclared_identifier*/ + var page_global = 42; + //--> + </script> + <script type="text/javascript"><!-- + myglobal.set(page_global); + undef(); /*warning:undeclared_identifier*/ + //--> + </script> +</head> +<body> +</body> +</html> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |