Thread: [javascriptlint-commit] SF.net SVN: javascriptlint:[213] trunk
Status: Beta
Brought to you by:
matthiasmiller
From: <mat...@us...> - 2008-08-23 23:14:12
|
Revision: 213 http://javascriptlint.svn.sourceforge.net/javascriptlint/?rev=213&view=rev Author: matthiasmiller Date: 2008-08-23 23:14:10 +0000 (Sat, 23 Aug 2008) Log Message: ----------- first cut at implementing fallthru Modified Paths: -------------- trunk/pyjsl/lint.py trunk/pyjsl/warnings.py trunk/tests/warnings/missing_default_case.js Modified: trunk/pyjsl/lint.py =================================================================== --- trunk/pyjsl/lint.py 2008-08-23 22:32:48 UTC (rev 212) +++ trunk/pyjsl/lint.py 2008-08-23 23:14:10 UTC (rev 213) @@ -159,6 +159,29 @@ parse_errors.append((jsparse.NodePos(row, col), msg)) def report(node, errname): + if errname == 'missing_break': + # Find the end of the previous case/default and the beginning of + # the next case/default. + assert node.kind in (tok.CASE, tok.DEFAULT) + prevnode = node.parent.kids[node.node_index-1] + expectedfallthru = prevnode.end_pos(), node.start_pos() + elif errname == 'missing_break_for_last_case': + # Find the end of the current case/default and the end of the + # switch. + assert node.parent.kind == tok.LC + expectedfallthru = node.end_pos(), node.parent.end_pos() + else: + expectedfallthru = None + + if expectedfallthru: + start, end = expectedfallthru + for fallthru in fallthrus: + # Look for a fallthru between the end of the current case or + # default statement and the beginning of the next token. + if fallthru.start_pos() > start and fallthru.end_pos() < end: + fallthrus.remove(fallthru) + return + _report(node.start_pos(), errname, True) def _report(pos, errname, require_key): @@ -185,6 +208,7 @@ start_ignore = None declares = [] import_paths = [] + fallthrus = [] for comment in comments: cc = _parse_control_comment(comment) if cc: @@ -210,6 +234,8 @@ report(node, 'jsl_cc_not_understood') else: import_paths.append(parms) + elif keyword == 'fallthru': + fallthrus.append(node) else: if comment.opcode == 'c_comment': if '/*' in comment.atom or comment.atom.endswith('/'): @@ -244,6 +270,9 @@ if root: _lint_node(root, visitors) + for fallthru in fallthrus: + report(fallthru, 'invalid_fallthru') + # Process imports by copying global declarations into the universal scope. imports |= set(conf['declarations']) imports |= _globals Modified: trunk/pyjsl/warnings.py =================================================================== --- trunk/pyjsl/warnings.py 2008-08-23 22:32:48 UTC (rev 212) +++ trunk/pyjsl/warnings.py 2008-08-23 23:14:10 UTC (rev 213) @@ -65,6 +65,7 @@ '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', + 'invalid_fallthru': 'unexpected "fallthru" control comment' } _visitors = [] Modified: trunk/tests/warnings/missing_default_case.js =================================================================== --- trunk/tests/warnings/missing_default_case.js 2008-08-23 22:32:48 UTC (rev 212) +++ trunk/tests/warnings/missing_default_case.js 2008-08-23 23:14:10 UTC (rev 213) @@ -8,10 +8,10 @@ return 1; } - /* ambivalence - allow fallthru but don't enforce it */ + /* ambivalence - fallthru is meaningless */ switch (i) { case 2: - /*jsl:fallthru*/ + /*jsl:fallthru*/ /*warning:invalid_fallthru*/ case 3: s += 1; break; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mat...@us...> - 2008-08-23 23:58:16
|
Revision: 214 http://javascriptlint.svn.sourceforge.net/javascriptlint/?rev=214&view=rev Author: matthiasmiller Date: 2008-08-23 23:58:12 +0000 (Sat, 23 Aug 2008) Log Message: ----------- first cut at supporting jsl:pass Modified Paths: -------------- trunk/pyjsl/lint.py trunk/pyjsl/warnings.py trunk/spidermonkey/src/jsparse.c trunk/test.py trunk/tests/path_resolution/asterisk.js trunk/tests/path_resolution/is_a_file_not_dir.js trunk/tests/path_resolution/not_a_dir.js trunk/tests/path_resolution/not_a_file.js trunk/tests/path_resolution/question_mark.js Added Paths: ----------- trunk/tests/control_comments/invalid_pass.js Modified: trunk/pyjsl/lint.py =================================================================== --- trunk/pyjsl/lint.py 2008-08-23 23:14:10 UTC (rev 213) +++ trunk/pyjsl/lint.py 2008-08-23 23:58:12 UTC (rev 214) @@ -156,9 +156,16 @@ def _lint_script(script, script_cache, lint_error, conf, import_callback): def parse_error(row, col, msg): if not msg in ('redeclared_var', 'var_hides_arg'): - parse_errors.append((jsparse.NodePos(row, col), msg)) + parse_errors.append((jsparse.NodePos(row, col), msg)) def report(node, errname): + if errname == 'empty_statement' and node.kind == tok.LC: + for pass_ in passes: + if pass_.start_pos() > node.start_pos() and \ + pass_.end_pos() < node.end_pos(): + passes.remove(pass_) + return + if errname == 'missing_break': # Find the end of the previous case/default and the beginning of # the next case/default. @@ -209,6 +216,7 @@ declares = [] import_paths = [] fallthrus = [] + passes = [] for comment in comments: cc = _parse_control_comment(comment) if cc: @@ -236,6 +244,8 @@ import_paths.append(parms) elif keyword == 'fallthru': fallthrus.append(node) + elif keyword == 'pass': + passes.append(node) else: if comment.opcode == 'c_comment': if '/*' in comment.atom or comment.atom.endswith('/'): @@ -272,6 +282,8 @@ for fallthru in fallthrus: report(fallthru, 'invalid_fallthru') + for fallthru in passes: + report(fallthru, 'invalid_pass') # Process imports by copying global declarations into the universal scope. imports |= set(conf['declarations']) Modified: trunk/pyjsl/warnings.py =================================================================== --- trunk/pyjsl/warnings.py 2008-08-23 23:14:10 UTC (rev 213) +++ trunk/pyjsl/warnings.py 2008-08-23 23:58:12 UTC (rev 214) @@ -65,7 +65,8 @@ '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', - 'invalid_fallthru': 'unexpected "fallthru" control comment' + 'invalid_fallthru': 'unexpected "fallthru" control comment', + 'invalid_pass': 'unexpected "pass" control comment' } _visitors = [] Modified: trunk/spidermonkey/src/jsparse.c =================================================================== --- trunk/spidermonkey/src/jsparse.c 2008-08-23 23:14:10 UTC (rev 213) +++ trunk/spidermonkey/src/jsparse.c 2008-08-23 23:58:12 UTC (rev 214) @@ -1519,7 +1519,9 @@ if (tt == TOK_ERROR) return NULL; - pn->pn_pos.end = CURRENT_TOKEN(ts).pos.end; + /* Set the LC's end position to the start of the RC. The stream is + * guaranteed to have a lookahead because of the peek above. */ + pn->pn_pos.end = ts->tokens[(ts->cursor+ts->lookahead) & NTOKENS_MASK].pos.begin; return pn; } Modified: trunk/test.py =================================================================== --- trunk/test.py 2008-08-23 23:14:10 UTC (rev 213) +++ trunk/test.py 2008-08-23 23:58:12 UTC (rev 214) @@ -24,7 +24,7 @@ for i in range(0, len(lines)): for warning in regexp.findall(lines[i]): # TODO: implement these - unimpl_warnings = ('ambiguous_newline', 'dup_option_explicit', 'invalid_pass', + unimpl_warnings = ('ambiguous_newline', 'dup_option_explicit', 'missing_semicolon' ) if not warning in unimpl_warnings: Added: trunk/tests/control_comments/invalid_pass.js =================================================================== --- trunk/tests/control_comments/invalid_pass.js (rev 0) +++ trunk/tests/control_comments/invalid_pass.js 2008-08-23 23:58:12 UTC (rev 214) @@ -0,0 +1,2 @@ +/*jsl:option explicit*/ +/*jsl:pass*/ /*warning:invalid_pass*/ Modified: trunk/tests/path_resolution/asterisk.js =================================================================== --- trunk/tests/path_resolution/asterisk.js 2008-08-23 23:14:10 UTC (rev 213) +++ trunk/tests/path_resolution/asterisk.js 2008-08-23 23:58:12 UTC (rev 214) @@ -1,3 +1,2 @@ /*conf:+process unknown_dir/a*b */ /*conf_error:unable to resolve path: unknown_dir/a*b*/ -/*jsl:pass*/ Modified: trunk/tests/path_resolution/is_a_file_not_dir.js =================================================================== --- trunk/tests/path_resolution/is_a_file_not_dir.js 2008-08-23 23:14:10 UTC (rev 213) +++ trunk/tests/path_resolution/is_a_file_not_dir.js 2008-08-23 23:58:12 UTC (rev 214) @@ -1,3 +1,2 @@ /*conf:+process file/ */ /*conf_error:unable to resolve path: file/*/ -/*jsl:pass*/ Modified: trunk/tests/path_resolution/not_a_dir.js =================================================================== --- trunk/tests/path_resolution/not_a_dir.js 2008-08-23 23:14:10 UTC (rev 213) +++ trunk/tests/path_resolution/not_a_dir.js 2008-08-23 23:58:12 UTC (rev 214) @@ -1,3 +1,2 @@ /*conf:+process not_a_dir*/ /*conf_error:unable to resolve path: not_a_dir*/ -/*jsl:pass*/ Modified: trunk/tests/path_resolution/not_a_file.js =================================================================== --- trunk/tests/path_resolution/not_a_file.js 2008-08-23 23:14:10 UTC (rev 213) +++ trunk/tests/path_resolution/not_a_file.js 2008-08-23 23:58:12 UTC (rev 214) @@ -1,3 +1,2 @@ /*conf:+process not_a_file*/ /*conf_error:unable to resolve path: not_a_file*/ -/*jsl:pass*/ Modified: trunk/tests/path_resolution/question_mark.js =================================================================== --- trunk/tests/path_resolution/question_mark.js 2008-08-23 23:14:10 UTC (rev 213) +++ trunk/tests/path_resolution/question_mark.js 2008-08-23 23:58:12 UTC (rev 214) @@ -1,3 +1,2 @@ /*conf:+process unknown_dir/a?b */ /*conf_error:unable to resolve path: unknown_dir/a?b*/ -/*jsl:pass*/ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mat...@us...> - 2008-08-24 00:37:06
|
Revision: 215 http://javascriptlint.svn.sourceforge.net/javascriptlint/?rev=215&view=rev Author: matthiasmiller Date: 2008-08-24 00:37:04 +0000 (Sun, 24 Aug 2008) Log Message: ----------- useless_quotes: only warn if the text would be syntactically valid Modified Paths: -------------- trunk/jsl.py trunk/pyjsl/lint.py trunk/pyjsl/util.py trunk/pyjsl/warnings.py trunk/tests/warnings/ambiguous_newline.js Modified: trunk/jsl.py =================================================================== --- trunk/jsl.py 2008-08-23 23:58:12 UTC (rev 214) +++ trunk/jsl.py 2008-08-24 00:37:04 UTC (rev 215) @@ -129,8 +129,12 @@ profile_func = profile_enabled if options.unittest: + suite = unittest.TestSuite(); + for module in [pyjsl.jsparse, pyjsl.util]: + suite.addTest(unittest.findTestCases(module)) + runner = unittest.TextTestRunner(verbosity=options.verbosity) - runner.run(unittest.findTestCases(pyjsl.jsparse)) + runner.run(suite) if options.test: profile_func(run_tests) Modified: trunk/pyjsl/lint.py =================================================================== --- trunk/pyjsl/lint.py 2008-08-23 23:58:12 UTC (rev 214) +++ trunk/pyjsl/lint.py 2008-08-24 00:37:04 UTC (rev 215) @@ -29,8 +29,6 @@ 'arguments', 'undefined' ]) -_identifier = re.compile('^[A-Za-z_$][A-Za-z0-9_$]*$') - def _find_function(node): while node and node.kind != tok.FUNCTION: node = node.parent @@ -222,7 +220,7 @@ if cc: node, keyword, parms = cc if keyword == 'declare': - if not _identifier.match(parms): + if not util.isidentifier(parms): report(node, 'jsl_cc_not_understood') else: declares.append((parms, node)) Modified: trunk/pyjsl/util.py =================================================================== --- trunk/pyjsl/util.py 2008-08-23 23:58:12 UTC (rev 214) +++ trunk/pyjsl/util.py 2008-08-24 00:37:04 UTC (rev 215) @@ -1,7 +1,14 @@ # vim: ts=4 sw=4 expandtab import codecs import os.path +import re +import unittest +_identifier = re.compile('^[A-Za-z_$][A-Za-z0-9_$]*$') + +def isidentifier(text): + return _identifier.match(text) + def readfile(path): file = codecs.open(path, 'r', 'utf-8') contents = file.read() @@ -15,3 +22,14 @@ path = os.path.normpath(path) return path +class TestUtil(unittest.TestCase): + def testIdentifier(self): + assert not isidentifier('') + assert not isidentifier('0a') + assert not isidentifier('a b') + assert isidentifier('a') + assert isidentifier('$0') + +if __name__ == '__main__': + unittest.main() + Modified: trunk/pyjsl/warnings.py =================================================================== --- trunk/pyjsl/warnings.py 2008-08-23 23:58:12 UTC (rev 214) +++ trunk/pyjsl/warnings.py 2008-08-24 00:37:04 UTC (rev 215) @@ -18,6 +18,7 @@ import sys import types +import util import visitation from pyspidermonkey import tok, op @@ -420,7 +421,9 @@ @lookfor(tok.STRING) def useless_quotes(node): if node.node_index == 0 and node.parent.kind == tok.COLON: - raise LintWarning, node + # Only warn if the quotes could safely be removed. + if util.isidentifier(node.atom): + raise LintWarning, node @lookfor() def mismatch_ctrl_comments(node): Modified: trunk/tests/warnings/ambiguous_newline.js =================================================================== --- trunk/tests/warnings/ambiguous_newline.js 2008-08-23 23:58:12 UTC (rev 214) +++ trunk/tests/warnings/ambiguous_newline.js 2008-08-24 00:37:04 UTC (rev 215) @@ -185,8 +185,8 @@ /* legal */ o = { - 'one': 1, - 'two': 2 + one: 1, + two: 2 }; /* legal */ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mat...@us...> - 2008-08-26 03:11:07
|
Revision: 217 http://javascriptlint.svn.sourceforge.net/javascriptlint/?rev=217&view=rev Author: matthiasmiller Date: 2008-08-26 03:11:02 +0000 (Tue, 26 Aug 2008) Log Message: ----------- unreferenced_identifier: first cut at implementation Modified Paths: -------------- trunk/pyjsl/lint.py trunk/pyjsl/warnings.py trunk/tests/control_comments/declare.js trunk/tests/control_comments/option_explicit-with.js trunk/tests/control_comments/option_explicit.js trunk/tests/warnings/ambiguous_newline.js trunk/tests/warnings/anon_no_return_value.js trunk/tests/warnings/duplicate_formal.js trunk/tests/warnings/inc_dec_within_stmt.js trunk/tests/warnings/misplaced_regex.js trunk/tests/warnings/missing_break.js trunk/tests/warnings/missing_semicolon.js trunk/tests/warnings/no_return_value.js trunk/tests/warnings/redeclared_var.js trunk/tests/warnings/spidermonkey/bad_backref.js trunk/tests/warnings/spidermonkey/invalid_backref.js trunk/tests/warnings/var_hides_arg.js Added Paths: ----------- trunk/tests/warnings/unreferenced_identifier.js Modified: trunk/pyjsl/lint.py =================================================================== --- trunk/pyjsl/lint.py 2008-08-24 00:39:17 UTC (rev 216) +++ trunk/pyjsl/lint.py 2008-08-26 03:11:02 UTC (rev 217) @@ -74,7 +74,6 @@ class Scope: def __init__(self, node): """ node may be None """ - self._is_with_scope = node and node.kind == tok.WITH self._parent = None self._kids = [] self._identifiers = {} @@ -83,15 +82,11 @@ def add_scope(self, node): self._kids.append(Scope(node)) self._kids[-1]._parent = self - if self._is_with_scope: - self._kids[-1]._is_with_scope = True return self._kids[-1] def add_declaration(self, name, node): - if not self._is_with_scope: - self._identifiers[name] = node + self._identifiers[name] = node def add_reference(self, name, node): - if not self._is_with_scope: - self._references.append((name, node)) + self._references.append((name, node)) def get_identifier(self, name): if name in self._identifiers: return self._identifiers[name] @@ -106,14 +101,55 @@ if self._parent: return self._parent.resolve_identifier(name) return None - def get_undeclared_identifiers(self): - identifiers = [] + def get_unreferenced_and_undeclared_identifiers(self): + """ Returns a tuple of unreferenced and undeclared, where each is a list + of (scope, name, node) tuples. + """ + unreferenced = {} + undeclared = [] + self._find_unreferenced_and_undeclared(unreferenced, undeclared, False) + + # Convert "unreferenced" from a dictionary of: + # { (scope, name): node } + # to a list of: + # [ (scope, name, node) ] + # sorted by node position. + unreferenced = [(key[0], key[1], node) for key, node + in unreferenced.items()] + unreferenced.sort(key=lambda x: x[2].start_pos()) + + return unreferenced, undeclared + def _find_unreferenced_and_undeclared(self, unreferenced, undeclared, + is_in_with_scope): + """ unreferenced is a dictionary, such that: + (scope, name): node + } + undeclared is a list, such that: [ + (scope, name, node) + ] + """ + is_in_with_scope = is_in_with_scope or self._node.kind == tok.WITH + + # Add all identifiers as unreferenced. Children scopes will remove + # them if they are referenced. Variables need to be keyed by name + # instead of node, because function parameters share the same node. + for name, node in self._identifiers.items(): + unreferenced[(self, name)] = node + + # Remove all declared variables from the "unreferenced" set; add all + # undeclared variables to the "undeclared" list. + for name, node in self._references: + resolved = self.resolve_identifier(name) + if resolved: + unreferenced.pop((resolved[0], name), None) + else: + # with statements cannot have undeclared identifiers. + if not is_in_with_scope: + undeclared.append((self, name, node)) + for child in self._kids: - identifiers += child.get_undeclared_identifiers() - for name, node in self._references: - if not self.resolve_identifier(name): - identifiers.append(node) - return identifiers + child._find_unreferenced_and_undeclared(unreferenced, undeclared, + is_in_with_scope) def find_scope(self, node): if not self._node: return None @@ -298,9 +334,14 @@ else: declare_scope.add_declaration(name, node) - for node in scope.get_undeclared_identifiers(): - if not node.atom in imports: + unreferenced, undeclared = scope.get_unreferenced_and_undeclared_identifiers() + for decl_scope, name, node in undeclared: + if not name in imports: report(node, 'undeclared_identifier') + for ref_scope, name, node in unreferenced: + # Ignore the outer scope. + if ref_scope != scope: + report(node, 'unreferenced_identifier') def _getreporter(visitor, report): def onpush(node): @@ -328,11 +369,13 @@ @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: + return # left side of object literal + if node.parent.kind == tok.VAR: + _warn_or_declare(scopes[-1], node.atom, node, report) + return + if node.parent.kind == tok.CATCH: scopes[-1].add_declaration(node.atom, node) - else: - scopes[-1].add_reference(node.atom, node) + scopes[-1].add_reference(node.atom, node) @visitation.visit('push', tok.FUNCTION) def _push_func(self, node): @@ -350,11 +393,6 @@ 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(scopes[-1], kid.atom, node, report) - return scope_checks Modified: trunk/pyjsl/warnings.py =================================================================== --- trunk/pyjsl/warnings.py 2008-08-24 00:39:17 UTC (rev 216) +++ trunk/pyjsl/warnings.py 2008-08-26 03:11:02 UTC (rev 217) @@ -56,6 +56,7 @@ '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}', + 'unreferenced_identifier': 'identifier is declared but never referenced: {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', Modified: trunk/tests/control_comments/declare.js =================================================================== --- trunk/tests/control_comments/declare.js 2008-08-24 00:39:17 UTC (rev 216) +++ trunk/tests/control_comments/declare.js 2008-08-26 03:11:02 UTC (rev 217) @@ -1,4 +1,5 @@ /*jsl:option explicit*/ +/*conf:-unreferenced_identifier*/ function declare() { window.alert('http://www.javascriptlint.com/'); /*jsl:declare window*/ /*warning:redeclared_var*/ Modified: trunk/tests/control_comments/option_explicit-with.js =================================================================== --- trunk/tests/control_comments/option_explicit-with.js 2008-08-24 00:39:17 UTC (rev 216) +++ trunk/tests/control_comments/option_explicit-with.js 2008-08-26 03:11:02 UTC (rev 217) @@ -1,4 +1,5 @@ /*jsl:option explicit*/ +/*conf:-unreferenced_identifier*/ function option_explicit() { var o = {}; Modified: trunk/tests/control_comments/option_explicit.js =================================================================== --- trunk/tests/control_comments/option_explicit.js 2008-08-24 00:39:17 UTC (rev 216) +++ trunk/tests/control_comments/option_explicit.js 2008-08-26 03:11:02 UTC (rev 217) @@ -1,4 +1,5 @@ /*jsl:option explicit*/ +/*conf:-unreferenced_identifier*/ var g; function option_explicit(parm) { /* legal - j is declared */ Modified: trunk/tests/warnings/ambiguous_newline.js =================================================================== --- trunk/tests/warnings/ambiguous_newline.js 2008-08-24 00:39:17 UTC (rev 216) +++ trunk/tests/warnings/ambiguous_newline.js 2008-08-26 03:11:02 UTC (rev 217) @@ -1,4 +1,5 @@ /*jsl:option explicit*/ +/*conf:-unreferenced_identifier*/ function ambiguous_newline() { /* the EOL test is based on JSLint's documentation */ var a, b, i, o, s; Modified: trunk/tests/warnings/anon_no_return_value.js =================================================================== --- trunk/tests/warnings/anon_no_return_value.js 2008-08-24 00:39:17 UTC (rev 216) +++ trunk/tests/warnings/anon_no_return_value.js 2008-08-26 03:11:02 UTC (rev 217) @@ -1,4 +1,5 @@ /*jsl:option explicit*/ +/*conf:-unreferenced_identifier*/ function anon_no_return_value() { var error1 = function(b) { if (b) Modified: trunk/tests/warnings/duplicate_formal.js =================================================================== --- trunk/tests/warnings/duplicate_formal.js 2008-08-24 00:39:17 UTC (rev 216) +++ trunk/tests/warnings/duplicate_formal.js 2008-08-26 03:11:02 UTC (rev 217) @@ -1,5 +1,5 @@ /*jsl:option explicit*/ function duplicate_formal(duplicate, duplicate) { /*warning:duplicate_formal*/ - return; + return duplicate; } Modified: trunk/tests/warnings/inc_dec_within_stmt.js =================================================================== --- trunk/tests/warnings/inc_dec_within_stmt.js 2008-08-24 00:39:17 UTC (rev 216) +++ trunk/tests/warnings/inc_dec_within_stmt.js 2008-08-26 03:11:02 UTC (rev 217) @@ -1,4 +1,5 @@ /*jsl:option explicit*/ +/*conf:-unreferenced_identifier*/ function inc_dec_within_stmt() { var i, s; Modified: trunk/tests/warnings/misplaced_regex.js =================================================================== --- trunk/tests/warnings/misplaced_regex.js 2008-08-24 00:39:17 UTC (rev 216) +++ trunk/tests/warnings/misplaced_regex.js 2008-08-26 03:11:02 UTC (rev 217) @@ -1,4 +1,5 @@ /*jsl:option explicit*/ +/*conf:-unreferenced_identifier*/ function misplaced_regex() { var i, re; Modified: trunk/tests/warnings/missing_break.js =================================================================== --- trunk/tests/warnings/missing_break.js 2008-08-24 00:39:17 UTC (rev 216) +++ trunk/tests/warnings/missing_break.js 2008-08-26 03:11:02 UTC (rev 217) @@ -1,4 +1,5 @@ /*jsl:option explicit*/ +/*conf:-unreferenced_identifier*/ function missing_break() { var i, o, s; Modified: trunk/tests/warnings/missing_semicolon.js =================================================================== --- trunk/tests/warnings/missing_semicolon.js 2008-08-24 00:39:17 UTC (rev 216) +++ trunk/tests/warnings/missing_semicolon.js 2008-08-26 03:11:02 UTC (rev 217) @@ -1,7 +1,7 @@ /*jsl:option explicit*/ function missing_semicolon() { /* missing semicolon after return */ - function MissingSemicolonOnReturnStatement() { + function MissingSemicolonOnReturnStatement() { /*warning:unreferenced_identifier*/ return 0 } /*warning:missing_semicolon*/ Modified: trunk/tests/warnings/no_return_value.js =================================================================== --- trunk/tests/warnings/no_return_value.js 2008-08-24 00:39:17 UTC (rev 216) +++ trunk/tests/warnings/no_return_value.js 2008-08-26 03:11:02 UTC (rev 217) @@ -1,4 +1,5 @@ /*jsl:option explicit*/ +/*conf:-unreferenced_identifier*/ function no_return_value() { function error1(b) { if (b) Modified: trunk/tests/warnings/redeclared_var.js =================================================================== --- trunk/tests/warnings/redeclared_var.js 2008-08-24 00:39:17 UTC (rev 216) +++ trunk/tests/warnings/redeclared_var.js 2008-08-26 03:11:02 UTC (rev 217) @@ -1,4 +1,5 @@ /*jsl:option explicit*/ +/*conf:-unreferenced_identifier*/ function redeclared_var() { var duplicate; var duplicate; /*warning:redeclared_var*/ Modified: trunk/tests/warnings/spidermonkey/bad_backref.js =================================================================== --- trunk/tests/warnings/spidermonkey/bad_backref.js 2008-08-24 00:39:17 UTC (rev 216) +++ trunk/tests/warnings/spidermonkey/bad_backref.js 2008-08-26 03:11:02 UTC (rev 217) @@ -1,5 +1,5 @@ /*jsl:option explicit*/ function bad_backref() { /* illegal - one 1 backreference */ - var re = /(.)\2/; /*warning:bad_backref*/ + return /(.)\2/; /*warning:bad_backref*/ } Modified: trunk/tests/warnings/spidermonkey/invalid_backref.js =================================================================== --- trunk/tests/warnings/spidermonkey/invalid_backref.js 2008-08-24 00:39:17 UTC (rev 216) +++ trunk/tests/warnings/spidermonkey/invalid_backref.js 2008-08-26 03:11:02 UTC (rev 217) @@ -1,5 +1,5 @@ /*jsl:option explicit*/ function invalid_backref() { /* illegal - \0 is not a valid regex backreference */ - var re = /\0/; /*warning:invalid_backref*/ + return /\0/; /*warning:invalid_backref*/ } Added: trunk/tests/warnings/unreferenced_identifier.js =================================================================== --- trunk/tests/warnings/unreferenced_identifier.js (rev 0) +++ trunk/tests/warnings/unreferenced_identifier.js 2008-08-26 03:11:02 UTC (rev 217) @@ -0,0 +1,56 @@ +/* outer-level functions shouldn't warn */ +var unreferenced_global; +function unreferenced_identifier() { + /* Test an unreferenced function. */ + function unreferenced_func() { /*warning:unreferenced_identifier*/ + return true; + } + function referenced_func() { + } + var referenced_var = referenced_func; + referenced_var(); + + /* Test an unreferenced parameter. */ + var z = new function(unreferenced_parm) { /*warning:unreferenced_identifier*/ + } + z.prop = 42; + + /* Test an unreferenced variable. */ + var unreferenced_variable = 100; /*warning:unreferenced_identifier*/ + + /* An unreferenced duplicate parameter should give one warning. */ + function func_with_dup(unref_dup_parm, unref_dup_parm) { /*warning:unreferenced_identifier*/ /*warning:duplicate_formal*/ + } + func_with_dup(); + + /* An unreferenced duplicate variable should give one warning. */ + var unref_dup_var; /*warning:unreferenced_identifier*/ + var unref_dup_var; /*warning:redeclared_var*/ + + /* Test a try/catch. The error doesn't need to be referenced. */ + var can; + try { + can = true; /* we think we can... */ + } + catch(err) { + can = false; /* ...but maybe not! */ + } + + /* Test a with statement. */ + var withobj = {}; + var withval = 42; + with (withobj) /*warning:with_statement*/ + { + prop_a = withval; + var innerval = '42'; + prop_b = innerval; + } + + /* Test nested scopes. */ + function get_callback(parm) { + return function() { + return parm; + } + } + return get_callback(42); +} Modified: trunk/tests/warnings/var_hides_arg.js =================================================================== --- trunk/tests/warnings/var_hides_arg.js 2008-08-24 00:39:17 UTC (rev 216) +++ trunk/tests/warnings/var_hides_arg.js 2008-08-26 03:11:02 UTC (rev 217) @@ -1,4 +1,5 @@ /*jsl:option explicit*/ +/*conf:-unreferenced_identifier*/ function var_hides_arg(duplicate1, duplicate2) { var duplicate1; /*warning:var_hides_arg*/ function inner() { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mat...@us...> - 2008-08-26 03:32:40
|
Revision: 218 http://javascriptlint.svn.sourceforge.net/javascriptlint/?rev=218&view=rev Author: matthiasmiller Date: 2008-08-26 03:32:35 +0000 (Tue, 26 Aug 2008) Log Message: ----------- unreferenced_identifier: improve warning to ignore variable assignments Modified Paths: -------------- trunk/pyjsl/lint.py trunk/tests/warnings/assign_to_function_call.js trunk/tests/warnings/duplicate_case_in_switch.js trunk/tests/warnings/inc_dec_within_stmt-ignore.js trunk/tests/warnings/leading_decimal_point.js trunk/tests/warnings/missing_default_case.js trunk/tests/warnings/octal_number.js trunk/tests/warnings/parseint_missing_radix.js trunk/tests/warnings/trailing_comma_in_array.js trunk/tests/warnings/trailing_decimal_point.js trunk/tests/warnings/unreferenced_identifier.js trunk/tests/warnings/useless_quotes.js Modified: trunk/pyjsl/lint.py =================================================================== --- trunk/pyjsl/lint.py 2008-08-26 03:11:02 UTC (rev 217) +++ trunk/pyjsl/lint.py 2008-08-26 03:32:35 UTC (rev 218) @@ -141,6 +141,11 @@ for name, node in self._references: resolved = self.resolve_identifier(name) if resolved: + # Make sure this isn't an assignment. + if node.parent.kind == tok.ASSIGN and \ + node.node_index == 0 and \ + node.parent.parent.kind == tok.SEMI: + continue unreferenced.pop((resolved[0], name), None) else: # with statements cannot have undeclared identifiers. Modified: trunk/tests/warnings/assign_to_function_call.js =================================================================== --- trunk/tests/warnings/assign_to_function_call.js 2008-08-26 03:11:02 UTC (rev 217) +++ trunk/tests/warnings/assign_to_function_call.js 2008-08-26 03:32:35 UTC (rev 218) @@ -1,4 +1,5 @@ /*jsl:option explicit*/ +/*conf:-unreferenced_identifier*/ function assign_to_function_call() { var o; var s; Modified: trunk/tests/warnings/duplicate_case_in_switch.js =================================================================== --- trunk/tests/warnings/duplicate_case_in_switch.js 2008-08-26 03:11:02 UTC (rev 217) +++ trunk/tests/warnings/duplicate_case_in_switch.js 2008-08-26 03:32:35 UTC (rev 218) @@ -1,4 +1,5 @@ /*jsl:option explicit*/ +/*conf:-unreferenced_identifier*/ function duplicate_case_in_switch() { var i, o, s; Modified: trunk/tests/warnings/inc_dec_within_stmt-ignore.js =================================================================== --- trunk/tests/warnings/inc_dec_within_stmt-ignore.js 2008-08-26 03:11:02 UTC (rev 217) +++ trunk/tests/warnings/inc_dec_within_stmt-ignore.js 2008-08-26 03:32:35 UTC (rev 218) @@ -1,4 +1,5 @@ /*jsl:option explicit*/ +/*conf:-unreferenced_identifier*/ function inc_dec_within_stmt() { var x; do { Modified: trunk/tests/warnings/leading_decimal_point.js =================================================================== --- trunk/tests/warnings/leading_decimal_point.js 2008-08-26 03:11:02 UTC (rev 217) +++ trunk/tests/warnings/leading_decimal_point.js 2008-08-26 03:32:35 UTC (rev 218) @@ -1,4 +1,5 @@ /*jsl:option explicit*/ +/*conf:-unreferenced_identifier*/ function leading_decimal_point() { var i; Modified: trunk/tests/warnings/missing_default_case.js =================================================================== --- trunk/tests/warnings/missing_default_case.js 2008-08-26 03:11:02 UTC (rev 217) +++ trunk/tests/warnings/missing_default_case.js 2008-08-26 03:32:35 UTC (rev 218) @@ -1,4 +1,5 @@ /*jsl:option explicit*/ +/*conf:-unreferenced_identifier*/ function missing_default_case() { var i, s; Modified: trunk/tests/warnings/octal_number.js =================================================================== --- trunk/tests/warnings/octal_number.js 2008-08-26 03:11:02 UTC (rev 217) +++ trunk/tests/warnings/octal_number.js 2008-08-26 03:32:35 UTC (rev 218) @@ -1,4 +1,5 @@ /*jsl:option explicit*/ +/*conf:-unreferenced_identifier*/ function octal_number() { var i; i = 010; /*warning:octal_number*/ Modified: trunk/tests/warnings/parseint_missing_radix.js =================================================================== --- trunk/tests/warnings/parseint_missing_radix.js 2008-08-26 03:11:02 UTC (rev 217) +++ trunk/tests/warnings/parseint_missing_radix.js 2008-08-26 03:32:35 UTC (rev 218) @@ -1,4 +1,5 @@ /*jsl:option explicit*/ +/*conf:-unreferenced_identifier*/ function parseint_missing_radix() { var i; Modified: trunk/tests/warnings/trailing_comma_in_array.js =================================================================== --- trunk/tests/warnings/trailing_comma_in_array.js 2008-08-26 03:11:02 UTC (rev 217) +++ trunk/tests/warnings/trailing_comma_in_array.js 2008-08-26 03:32:35 UTC (rev 218) @@ -1,4 +1,5 @@ /*jsl:option explicit*/ +/*conf:-unreferenced_identifier*/ function trailing_comma_in_array() { var a; Modified: trunk/tests/warnings/trailing_decimal_point.js =================================================================== --- trunk/tests/warnings/trailing_decimal_point.js 2008-08-26 03:11:02 UTC (rev 217) +++ trunk/tests/warnings/trailing_decimal_point.js 2008-08-26 03:32:35 UTC (rev 218) @@ -1,4 +1,5 @@ /*jsl:option explicit*/ +/*conf:-unreferenced_identifier*/ function trailing_decimal_point() { var i; Modified: trunk/tests/warnings/unreferenced_identifier.js =================================================================== --- trunk/tests/warnings/unreferenced_identifier.js 2008-08-26 03:11:02 UTC (rev 217) +++ trunk/tests/warnings/unreferenced_identifier.js 2008-08-26 03:32:35 UTC (rev 218) @@ -35,6 +35,7 @@ catch(err) { can = false; /* ...but maybe not! */ } + can = !can; /* Test a with statement. */ var withobj = {}; @@ -46,6 +47,15 @@ prop_b = innerval; } + /* Test assignments. */ + var assigned_but_unref; /*warning:unreferenced_identifier*/ + assigned_but_unref = 42; + + function callback() { + } + var assigned_but_ref; + (assigned_but_ref = callback)(); + /* Test nested scopes. */ function get_callback(parm) { return function() { Modified: trunk/tests/warnings/useless_quotes.js =================================================================== --- trunk/tests/warnings/useless_quotes.js 2008-08-26 03:11:02 UTC (rev 217) +++ trunk/tests/warnings/useless_quotes.js 2008-08-26 03:32:35 UTC (rev 218) @@ -1,3 +1,4 @@ +/*conf:-unreferenced_identifier*/ function useless_quotes() { var o = { 'key': 1 /*warning:useless_quotes*/ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mat...@us...> - 2008-08-26 03:50:20
|
Revision: 219 http://javascriptlint.svn.sourceforge.net/javascriptlint/?rev=219&view=rev Author: matthiasmiller Date: 2008-08-26 03:50:14 +0000 (Tue, 26 Aug 2008) Log Message: ----------- unreferenced_identifier: by default, disable for tests to reduce noise Modified Paths: -------------- trunk/test.py trunk/tests/control_comments/declare.js trunk/tests/control_comments/option_explicit-with.js trunk/tests/control_comments/option_explicit.js trunk/tests/warnings/ambiguous_newline.js trunk/tests/warnings/anon_no_return_value.js trunk/tests/warnings/assign_to_function_call.js trunk/tests/warnings/duplicate_case_in_switch.js trunk/tests/warnings/inc_dec_within_stmt-ignore.js trunk/tests/warnings/inc_dec_within_stmt.js trunk/tests/warnings/leading_decimal_point.js trunk/tests/warnings/misplaced_regex.js trunk/tests/warnings/missing_break.js trunk/tests/warnings/missing_default_case.js trunk/tests/warnings/missing_semicolon.js trunk/tests/warnings/no_return_value.js trunk/tests/warnings/octal_number.js trunk/tests/warnings/parseint_missing_radix.js trunk/tests/warnings/redeclared_var.js trunk/tests/warnings/trailing_comma_in_array.js trunk/tests/warnings/trailing_decimal_point.js trunk/tests/warnings/unreferenced_identifier.js trunk/tests/warnings/useless_quotes.js trunk/tests/warnings/var_hides_arg.js Modified: trunk/test.py =================================================================== --- trunk/test.py 2008-08-26 03:32:35 UTC (rev 218) +++ trunk/test.py 2008-08-26 03:50:14 UTC (rev 219) @@ -4,6 +4,12 @@ import pyjsl.conf import pyjsl.lint +_DEFAULT_CONF = """ +# This warning triggers a lot of warnings in many of the tests, so only enable +# it when specifically testing it. +-unreferenced_identifier +""" + class TestError(Exception): pass @@ -11,6 +17,7 @@ regexp = re.compile(r"/\*conf:([^*]*)\*/") text = '\n'.join(regexp.findall(script)) conf = pyjsl.conf.Conf() + conf.loadtext(_DEFAULT_CONF) conf.loadtext(text) return conf Modified: trunk/tests/control_comments/declare.js =================================================================== --- trunk/tests/control_comments/declare.js 2008-08-26 03:32:35 UTC (rev 218) +++ trunk/tests/control_comments/declare.js 2008-08-26 03:50:14 UTC (rev 219) @@ -1,5 +1,4 @@ /*jsl:option explicit*/ -/*conf:-unreferenced_identifier*/ function declare() { window.alert('http://www.javascriptlint.com/'); /*jsl:declare window*/ /*warning:redeclared_var*/ Modified: trunk/tests/control_comments/option_explicit-with.js =================================================================== --- trunk/tests/control_comments/option_explicit-with.js 2008-08-26 03:32:35 UTC (rev 218) +++ trunk/tests/control_comments/option_explicit-with.js 2008-08-26 03:50:14 UTC (rev 219) @@ -1,5 +1,4 @@ /*jsl:option explicit*/ -/*conf:-unreferenced_identifier*/ function option_explicit() { var o = {}; Modified: trunk/tests/control_comments/option_explicit.js =================================================================== --- trunk/tests/control_comments/option_explicit.js 2008-08-26 03:32:35 UTC (rev 218) +++ trunk/tests/control_comments/option_explicit.js 2008-08-26 03:50:14 UTC (rev 219) @@ -1,5 +1,4 @@ /*jsl:option explicit*/ -/*conf:-unreferenced_identifier*/ var g; function option_explicit(parm) { /* legal - j is declared */ Modified: trunk/tests/warnings/ambiguous_newline.js =================================================================== --- trunk/tests/warnings/ambiguous_newline.js 2008-08-26 03:32:35 UTC (rev 218) +++ trunk/tests/warnings/ambiguous_newline.js 2008-08-26 03:50:14 UTC (rev 219) @@ -1,5 +1,4 @@ /*jsl:option explicit*/ -/*conf:-unreferenced_identifier*/ function ambiguous_newline() { /* the EOL test is based on JSLint's documentation */ var a, b, i, o, s; Modified: trunk/tests/warnings/anon_no_return_value.js =================================================================== --- trunk/tests/warnings/anon_no_return_value.js 2008-08-26 03:32:35 UTC (rev 218) +++ trunk/tests/warnings/anon_no_return_value.js 2008-08-26 03:50:14 UTC (rev 219) @@ -1,5 +1,4 @@ /*jsl:option explicit*/ -/*conf:-unreferenced_identifier*/ function anon_no_return_value() { var error1 = function(b) { if (b) Modified: trunk/tests/warnings/assign_to_function_call.js =================================================================== --- trunk/tests/warnings/assign_to_function_call.js 2008-08-26 03:32:35 UTC (rev 218) +++ trunk/tests/warnings/assign_to_function_call.js 2008-08-26 03:50:14 UTC (rev 219) @@ -1,5 +1,4 @@ /*jsl:option explicit*/ -/*conf:-unreferenced_identifier*/ function assign_to_function_call() { var o; var s; Modified: trunk/tests/warnings/duplicate_case_in_switch.js =================================================================== --- trunk/tests/warnings/duplicate_case_in_switch.js 2008-08-26 03:32:35 UTC (rev 218) +++ trunk/tests/warnings/duplicate_case_in_switch.js 2008-08-26 03:50:14 UTC (rev 219) @@ -1,5 +1,4 @@ /*jsl:option explicit*/ -/*conf:-unreferenced_identifier*/ function duplicate_case_in_switch() { var i, o, s; Modified: trunk/tests/warnings/inc_dec_within_stmt-ignore.js =================================================================== --- trunk/tests/warnings/inc_dec_within_stmt-ignore.js 2008-08-26 03:32:35 UTC (rev 218) +++ trunk/tests/warnings/inc_dec_within_stmt-ignore.js 2008-08-26 03:50:14 UTC (rev 219) @@ -1,5 +1,4 @@ /*jsl:option explicit*/ -/*conf:-unreferenced_identifier*/ function inc_dec_within_stmt() { var x; do { Modified: trunk/tests/warnings/inc_dec_within_stmt.js =================================================================== --- trunk/tests/warnings/inc_dec_within_stmt.js 2008-08-26 03:32:35 UTC (rev 218) +++ trunk/tests/warnings/inc_dec_within_stmt.js 2008-08-26 03:50:14 UTC (rev 219) @@ -1,5 +1,4 @@ /*jsl:option explicit*/ -/*conf:-unreferenced_identifier*/ function inc_dec_within_stmt() { var i, s; Modified: trunk/tests/warnings/leading_decimal_point.js =================================================================== --- trunk/tests/warnings/leading_decimal_point.js 2008-08-26 03:32:35 UTC (rev 218) +++ trunk/tests/warnings/leading_decimal_point.js 2008-08-26 03:50:14 UTC (rev 219) @@ -1,5 +1,4 @@ /*jsl:option explicit*/ -/*conf:-unreferenced_identifier*/ function leading_decimal_point() { var i; Modified: trunk/tests/warnings/misplaced_regex.js =================================================================== --- trunk/tests/warnings/misplaced_regex.js 2008-08-26 03:32:35 UTC (rev 218) +++ trunk/tests/warnings/misplaced_regex.js 2008-08-26 03:50:14 UTC (rev 219) @@ -1,5 +1,4 @@ /*jsl:option explicit*/ -/*conf:-unreferenced_identifier*/ function misplaced_regex() { var i, re; Modified: trunk/tests/warnings/missing_break.js =================================================================== --- trunk/tests/warnings/missing_break.js 2008-08-26 03:32:35 UTC (rev 218) +++ trunk/tests/warnings/missing_break.js 2008-08-26 03:50:14 UTC (rev 219) @@ -1,5 +1,4 @@ /*jsl:option explicit*/ -/*conf:-unreferenced_identifier*/ function missing_break() { var i, o, s; Modified: trunk/tests/warnings/missing_default_case.js =================================================================== --- trunk/tests/warnings/missing_default_case.js 2008-08-26 03:32:35 UTC (rev 218) +++ trunk/tests/warnings/missing_default_case.js 2008-08-26 03:50:14 UTC (rev 219) @@ -1,5 +1,4 @@ /*jsl:option explicit*/ -/*conf:-unreferenced_identifier*/ function missing_default_case() { var i, s; Modified: trunk/tests/warnings/missing_semicolon.js =================================================================== --- trunk/tests/warnings/missing_semicolon.js 2008-08-26 03:32:35 UTC (rev 218) +++ trunk/tests/warnings/missing_semicolon.js 2008-08-26 03:50:14 UTC (rev 219) @@ -1,7 +1,7 @@ /*jsl:option explicit*/ function missing_semicolon() { /* missing semicolon after return */ - function MissingSemicolonOnReturnStatement() { /*warning:unreferenced_identifier*/ + function MissingSemicolonOnReturnStatement() { return 0 } /*warning:missing_semicolon*/ Modified: trunk/tests/warnings/no_return_value.js =================================================================== --- trunk/tests/warnings/no_return_value.js 2008-08-26 03:32:35 UTC (rev 218) +++ trunk/tests/warnings/no_return_value.js 2008-08-26 03:50:14 UTC (rev 219) @@ -1,5 +1,4 @@ /*jsl:option explicit*/ -/*conf:-unreferenced_identifier*/ function no_return_value() { function error1(b) { if (b) Modified: trunk/tests/warnings/octal_number.js =================================================================== --- trunk/tests/warnings/octal_number.js 2008-08-26 03:32:35 UTC (rev 218) +++ trunk/tests/warnings/octal_number.js 2008-08-26 03:50:14 UTC (rev 219) @@ -1,5 +1,4 @@ /*jsl:option explicit*/ -/*conf:-unreferenced_identifier*/ function octal_number() { var i; i = 010; /*warning:octal_number*/ Modified: trunk/tests/warnings/parseint_missing_radix.js =================================================================== --- trunk/tests/warnings/parseint_missing_radix.js 2008-08-26 03:32:35 UTC (rev 218) +++ trunk/tests/warnings/parseint_missing_radix.js 2008-08-26 03:50:14 UTC (rev 219) @@ -1,5 +1,4 @@ /*jsl:option explicit*/ -/*conf:-unreferenced_identifier*/ function parseint_missing_radix() { var i; Modified: trunk/tests/warnings/redeclared_var.js =================================================================== --- trunk/tests/warnings/redeclared_var.js 2008-08-26 03:32:35 UTC (rev 218) +++ trunk/tests/warnings/redeclared_var.js 2008-08-26 03:50:14 UTC (rev 219) @@ -1,5 +1,4 @@ /*jsl:option explicit*/ -/*conf:-unreferenced_identifier*/ function redeclared_var() { var duplicate; var duplicate; /*warning:redeclared_var*/ Modified: trunk/tests/warnings/trailing_comma_in_array.js =================================================================== --- trunk/tests/warnings/trailing_comma_in_array.js 2008-08-26 03:32:35 UTC (rev 218) +++ trunk/tests/warnings/trailing_comma_in_array.js 2008-08-26 03:50:14 UTC (rev 219) @@ -1,5 +1,4 @@ /*jsl:option explicit*/ -/*conf:-unreferenced_identifier*/ function trailing_comma_in_array() { var a; Modified: trunk/tests/warnings/trailing_decimal_point.js =================================================================== --- trunk/tests/warnings/trailing_decimal_point.js 2008-08-26 03:32:35 UTC (rev 218) +++ trunk/tests/warnings/trailing_decimal_point.js 2008-08-26 03:50:14 UTC (rev 219) @@ -1,5 +1,4 @@ /*jsl:option explicit*/ -/*conf:-unreferenced_identifier*/ function trailing_decimal_point() { var i; Modified: trunk/tests/warnings/unreferenced_identifier.js =================================================================== --- trunk/tests/warnings/unreferenced_identifier.js 2008-08-26 03:32:35 UTC (rev 218) +++ trunk/tests/warnings/unreferenced_identifier.js 2008-08-26 03:50:14 UTC (rev 219) @@ -1,3 +1,6 @@ +/* The tests disable this warning by default becaues of noise. Enable it. */ +/*conf:+unreferenced_identifier*/ + /* outer-level functions shouldn't warn */ var unreferenced_global; function unreferenced_identifier() { Modified: trunk/tests/warnings/useless_quotes.js =================================================================== --- trunk/tests/warnings/useless_quotes.js 2008-08-26 03:32:35 UTC (rev 218) +++ trunk/tests/warnings/useless_quotes.js 2008-08-26 03:50:14 UTC (rev 219) @@ -1,4 +1,3 @@ -/*conf:-unreferenced_identifier*/ function useless_quotes() { var o = { 'key': 1 /*warning:useless_quotes*/ Modified: trunk/tests/warnings/var_hides_arg.js =================================================================== --- trunk/tests/warnings/var_hides_arg.js 2008-08-26 03:32:35 UTC (rev 218) +++ trunk/tests/warnings/var_hides_arg.js 2008-08-26 03:50:14 UTC (rev 219) @@ -1,5 +1,4 @@ /*jsl:option explicit*/ -/*conf:-unreferenced_identifier*/ function var_hides_arg(duplicate1, duplicate2) { var duplicate1; /*warning:var_hides_arg*/ function inner() { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mat...@us...> - 2008-08-26 13:54:33
|
Revision: 220 http://javascriptlint.svn.sourceforge.net/javascriptlint/?rev=220&view=rev Author: matthiasmiller Date: 2008-08-26 13:54:31 +0000 (Tue, 26 Aug 2008) Log Message: ----------- fix traceback with syntax errors Modified Paths: -------------- trunk/pyjsl/lint.py Added Paths: ----------- trunk/tests/errors/syntax_error.js Modified: trunk/pyjsl/lint.py =================================================================== --- trunk/pyjsl/lint.py 2008-08-26 03:50:14 UTC (rev 219) +++ trunk/pyjsl/lint.py 2008-08-26 13:54:31 UTC (rev 220) @@ -245,17 +245,26 @@ return lint_error(pos.line, pos.col, errname) parse_errors = [] - root = jsparse.parse(script, parse_error) - if root: - comments = jsparse.parsecomments(script, root) - else: - comments = [] ignores = [] - start_ignore = None declares = [] import_paths = [] fallthrus = [] passes = [] + + root = jsparse.parse(script, parse_error) + if not root: + # Cache empty results for this script. + assert not script_cache + script_cache['imports'] = set() + script_cache['scope'] = Scope(None) + + # Report errors and quit. + for pos, msg in parse_errors: + _report(pos, msg, False) + return + + comments = jsparse.parsecomments(script, root) + start_ignore = None for comment in comments: cc = _parse_control_comment(comment) if cc: @@ -316,8 +325,7 @@ visitation.make_visitors(visitors, [_get_scope_checks(scope, report)]) # kickoff! - if root: - _lint_node(root, visitors) + _lint_node(root, visitors) for fallthru in fallthrus: report(fallthru, 'invalid_fallthru') Added: trunk/tests/errors/syntax_error.js =================================================================== --- trunk/tests/errors/syntax_error.js (rev 0) +++ trunk/tests/errors/syntax_error.js 2008-08-26 13:54:31 UTC (rev 220) @@ -0,0 +1,4 @@ +function syntax_error() { + &; /*warning:syntax_error*/ +} + This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mat...@us...> - 2008-08-26 15:11:01
|
Revision: 221 http://javascriptlint.svn.sourceforge.net/javascriptlint/?rev=221&view=rev Author: matthiasmiller Date: 2008-08-26 15:10:59 +0000 (Tue, 26 Aug 2008) Log Message: ----------- want_assign_or_call: first cut at implementation Modified Paths: -------------- trunk/pyjsl/warnings.py trunk/tests/warnings/multiple_plus_minus.js Added Paths: ----------- trunk/tests/warnings/want_assign_or_call.js Modified: trunk/pyjsl/warnings.py =================================================================== --- trunk/pyjsl/warnings.py 2008-08-26 13:54:31 UTC (rev 220) +++ trunk/pyjsl/warnings.py 2008-08-26 15:10:59 UTC (rev 221) @@ -68,7 +68,8 @@ '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', 'invalid_fallthru': 'unexpected "fallthru" control comment', - 'invalid_pass': 'unexpected "pass" control comment' + 'invalid_pass': 'unexpected "pass" control comment', + 'want_assign_or_call': 'expected an assignment or function call' } _visitors = [] @@ -426,6 +427,25 @@ if util.isidentifier(node.atom): raise LintWarning, node +@lookfor(tok.SEMI) +def want_assign_or_call(node): + child, = node.kids + # Ignore empty statements. + if not child: + return + # NOTE: Don't handle comma-separated statements. + if child.kind in (tok.ASSIGN, tok.INC, tok.DEC, tok.DELETE, tok.COMMA): + return + # Ignore function calls. + if child.kind == tok.LP and child.opcode == op.CALL: + return + # Allow new function() { } as statements. + if child.kind == tok.NEW: + grandchild, = child.kids + if grandchild.kind == tok.FUNCTION: + return + raise LintWarning, child + @lookfor() def mismatch_ctrl_comments(node): pass Modified: trunk/tests/warnings/multiple_plus_minus.js =================================================================== --- trunk/tests/warnings/multiple_plus_minus.js 2008-08-26 13:54:31 UTC (rev 220) +++ trunk/tests/warnings/multiple_plus_minus.js 2008-08-26 15:10:59 UTC (rev 221) @@ -1,4 +1,5 @@ /*jsl:option explicit*/ +/*conf:-want_assign_or_call*/ function multiple_plus_minus() { var i, j; i = 0; Added: trunk/tests/warnings/want_assign_or_call.js =================================================================== --- trunk/tests/warnings/want_assign_or_call.js (rev 0) +++ trunk/tests/warnings/want_assign_or_call.js 2008-08-26 15:10:59 UTC (rev 221) @@ -0,0 +1,25 @@ +function want_assign_or_call() { + var a; + a; /*warning:want_assign_or_call*/ + a++; + a--; + a /= 2; + a %= 4; + a >>= 3; + a << 2; /*warning:want_assign_or_call*/ + + new function() { + }; + + function test() { + } + + function() { /*warning:want_assign_or_call*/ + return 42; + } + + delete a; + + a.b(); +} + This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mat...@us...> - 2008-08-26 16:06:36
|
Revision: 222 http://javascriptlint.svn.sourceforge.net/javascriptlint/?rev=222&view=rev Author: matthiasmiller Date: 2008-08-26 16:06:32 +0000 (Tue, 26 Aug 2008) Log Message: ----------- unreferenced_identifier: handle x++ and x-- Modified Paths: -------------- trunk/pyjsl/lint.py trunk/tests/warnings/unreferenced_identifier.js Modified: trunk/pyjsl/lint.py =================================================================== --- trunk/pyjsl/lint.py 2008-08-26 15:10:59 UTC (rev 221) +++ trunk/pyjsl/lint.py 2008-08-26 16:06:32 UTC (rev 222) @@ -142,7 +142,7 @@ resolved = self.resolve_identifier(name) if resolved: # Make sure this isn't an assignment. - if node.parent.kind == tok.ASSIGN and \ + if node.parent.kind in (tok.ASSIGN, tok.INC, tok.DEC) and \ node.node_index == 0 and \ node.parent.parent.kind == tok.SEMI: continue Modified: trunk/tests/warnings/unreferenced_identifier.js =================================================================== --- trunk/tests/warnings/unreferenced_identifier.js 2008-08-26 15:10:59 UTC (rev 221) +++ trunk/tests/warnings/unreferenced_identifier.js 2008-08-26 16:06:32 UTC (rev 222) @@ -59,6 +59,19 @@ var assigned_but_ref; (assigned_but_ref = callback)(); + /* Test increment and decrement. */ + var unref_inc; /*warning:unreferenced_identifier*/ + unref_inc++; + var unref_dec; /*warning:unreferenced_identifier*/ + unref_dec--; + + var tmp; + var ref_inc; + tmp = ref_inc++; /*warning:inc_dec_within_stmt*/ + var ref_dec; + tmp = ref_dec--; /*warning:inc_dec_within_stmt*/ + tmp = -tmp; + /* Test nested scopes. */ function get_callback(parm) { return function() { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mat...@us...> - 2008-08-27 01:58:43
|
Revision: 223 http://javascriptlint.svn.sourceforge.net/javascriptlint/?rev=223&view=rev Author: matthiasmiller Date: 2008-08-27 01:58:41 +0000 (Wed, 27 Aug 2008) Log Message: ----------- htmlparse: begin work on parsing HTML files Modified Paths: -------------- trunk/jsl.py Added Paths: ----------- trunk/pyjsl/htmlparse.py Modified: trunk/jsl.py =================================================================== --- trunk/jsl.py 2008-08-26 16:06:32 UTC (rev 222) +++ trunk/jsl.py 2008-08-27 01:58:41 UTC (rev 223) @@ -15,6 +15,7 @@ sys.path.append(setup.get_lib_path()) import pyjsl.conf +import pyjsl.htmlparse import pyjsl.jsparse import pyjsl.util import test @@ -130,7 +131,7 @@ if options.unittest: suite = unittest.TestSuite(); - for module in [pyjsl.jsparse, pyjsl.util]: + for module in [pyjsl.htmlparse, pyjsl.jsparse, pyjsl.util]: suite.addTest(unittest.findTestCases(module)) runner = unittest.TextTestRunner(verbosity=options.verbosity) Added: trunk/pyjsl/htmlparse.py =================================================================== --- trunk/pyjsl/htmlparse.py (rev 0) +++ trunk/pyjsl/htmlparse.py 2008-08-27 01:58:41 UTC (rev 223) @@ -0,0 +1,80 @@ +# vim: ts=4 sw=4 expandtab +import HTMLParser +import unittest + +import jsparse + +class _Parser(HTMLParser.HTMLParser): + def __init__(self): + HTMLParser.HTMLParser.__init__(self) + self._node_positions = jsparse.NodePositions('') + self._script = None + self._scripts = [] + + def handle_starttag(self, tag, attributes): + if tag.lower() == 'script' and not self._script: + offset = self._getoffset() + len(self.get_starttag_text()) + self._script = self._script or { + 'start': offset, + 'attributes': attributes + } + + def handle_endtag(self, tag): + if tag.lower() == 'script' and self._script: + start = self._script['start'] + end = self._getoffset() + script = self.rawdata[start:end] + if jsparse.is_compilable_unit(script): + attr = dict(self._script['attributes']) + self._scripts.append({ + 'script': script, + 'startoffset': start, + 'endoffset': end, + 'startpos': self._node_positions.from_offset(start), + 'endpos': self._node_positions.from_offset(end), + 'src': attr.get('src'), + 'type': attr.get('type') + }) + self._script = None + + def feed(self, data): + self._node_positions = jsparse.NodePositions(self.rawdata + data) + HTMLParser.HTMLParser.feed(self, data) + + def getscripts(self): + return self._scripts + + def _getnodepos(self): + line, col = self.getpos() + return jsparse.NodePos(line - 1, col) + + def _getoffset(self): + return self._node_positions.to_offset(self._getnodepos()) + +def findscripts(s): + parser = _Parser() + parser.feed(s) + parser.close() + return parser.getscripts() + +class TestHTMLParse(unittest.TestCase): + def testFindScript(self): + html = """ +<html><body> +<script src=test.js></script> +hi&b +a<script><!-- +var s = '<script></script>'; +--></script> +ok& +..</script> +ok& +</body> +</html> +""" + scripts = [x['script'] for x in findscripts(html)] + self.assertEquals(scripts, [ + "", + "<!--\nvar s = '<script></script>';\n-->" + ]) + Property changes on: trunk/pyjsl/htmlparse.py ___________________________________________________________________ Added: svn:eol-style + native This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mat...@us...> - 2008-08-28 00:02:53
|
Revision: 227 http://javascriptlint.svn.sourceforge.net/javascriptlint/?rev=227&view=rev Author: matthiasmiller Date: 2008-08-28 00:02:50 +0000 (Thu, 28 Aug 2008) Log Message: ----------- improve code flow warnings -change _get_exit_points to return the actual nodes -change the no_return_value, anon_no_return_value, and unreachable_code warnings to ignore declarations Modified Paths: -------------- trunk/pyjsl/lint.py trunk/pyjsl/warnings.py trunk/tests/warnings/anon_no_return_value.js trunk/tests/warnings/missing_break.js trunk/tests/warnings/no_return_value.js trunk/tests/warnings/unreachable_code.js Modified: trunk/pyjsl/lint.py =================================================================== --- trunk/pyjsl/lint.py 2008-08-27 16:11:25 UTC (rev 226) +++ trunk/pyjsl/lint.py 2008-08-28 00:02:50 UTC (rev 227) @@ -194,7 +194,8 @@ def _lint_script(script, script_cache, lint_error, conf, import_callback): def parse_error(row, col, msg): - if not msg in ('redeclared_var', 'var_hides_arg'): + if not msg in ('anon_no_return_value', 'no_return_value', + 'redeclared_var', 'var_hides_arg'): parse_errors.append((jsparse.NodePos(row, col), msg)) def report(node, errname): Modified: trunk/pyjsl/warnings.py =================================================================== --- trunk/pyjsl/warnings.py 2008-08-27 16:11:25 UTC (rev 226) +++ trunk/pyjsl/warnings.py 2008-08-28 00:02:50 UTC (rev 227) @@ -69,7 +69,9 @@ 'dup_option_explicit': 'duplicate "option explicit" control comment', 'invalid_fallthru': 'unexpected "fallthru" control comment', 'invalid_pass': 'unexpected "pass" control comment', - 'want_assign_or_call': 'expected an assignment or function call' + 'want_assign_or_call': 'expected an assignment or function call', + 'no_return_value': 'function {0} does not always return a value', + 'anon_no_return_value': 'anonymous function does not always return value' } _visitors = [] @@ -94,15 +96,22 @@ return None def _get_exit_points(node): + """ Returns a set of exit points, which may be: + * None, indicating a code path with no specific exit point. + * a node of type tok.BREAK, tok.RETURN, tok.THROW. + """ if node.kind == tok.LC: - # Only if the last child contains it exit_points = set([None]) for kid in node.kids: - # "None" is only a valid exit point for the last statement. - if None in exit_points: - exit_points.remove(None) if kid: - exit_points |= _get_exit_points(kid) + # Merge in the kid's exit points. + kid_exit_points = _get_exit_points(kid) + exit_points |= kid_exit_points + + # Stop if the kid always exits. + if not None in kid_exit_points: + exit_points.discard(None) + break elif node.kind == tok.IF: # Only if both branches have an exit point cond_, if_, else_ = node.kids @@ -126,10 +135,9 @@ # Correct the "None" exit point. exit_points.remove(None) - # Check if the switch contained any break - if tok.BREAK in exit_points: - exit_points.remove(tok.BREAK) - exit_points.add(None) + # Convert "break" into None + exit_points = set(map(lambda node: node \ + if node and node.kind != tok.BREAK else None, exit_points)) # Check if the switch had a default case if not switch_has_default: @@ -139,13 +147,13 @@ if switch_has_final_fallthru: exit_points.add(None) elif node.kind == tok.BREAK: - exit_points = set([tok.BREAK]) + exit_points = set([node]) elif node.kind == tok.WITH: exit_points = _get_exit_points(node.kids[-1]) elif node.kind == tok.RETURN: - exit_points = set([tok.RETURN]) + exit_points = set([node]) elif node.kind == tok.THROW: - exit_points = set([tok.THROW]) + exit_points = set([node]) elif node.kind == tok.TRY: try_, catch_, finally_ = node.kids @@ -369,9 +377,10 @@ @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] + if node.parent.kind == tok.LC: + for sibling in node.parent.kids[node.node_index+1:]: + if not sibling.kind in (tok.VAR, tok.FUNCTION): + raise LintWarning, sibling #TODO: @lookfor(tok.IF) def meaningless_block(node): @@ -446,6 +455,36 @@ return raise LintWarning, child +def _check_return_value(node): + def is_return_with_val(node): + return node and node.kind == tok.RETURN and node.kids[0] + def is_return_without_val(node): + return node and node.kind == tok.RETURN and not node.kids[0] + + node, = node.kids + assert node.kind == tok.LC + + exit_points = _get_exit_points(node) + if filter(is_return_with_val, exit_points): + # If the function returns a value, find all returns without a value. + returns = filter(is_return_without_val, exit_points) + returns.sort(key=lambda node: node.start_pos()) + if returns: + raise LintWarning, returns[0] + # Warn if the function sometimes exits naturally. + if None in exit_points: + raise LintWarning, node + +@lookfor(tok.FUNCTION) +def no_return_value(node): + if node.fn_name: + _check_return_value(node) + +@lookfor(tok.FUNCTION) +def anon_no_return_value(node): + if not node.fn_name: + _check_return_value(node) + @lookfor() def mismatch_ctrl_comments(node): pass Modified: trunk/tests/warnings/anon_no_return_value.js =================================================================== --- trunk/tests/warnings/anon_no_return_value.js 2008-08-27 16:11:25 UTC (rev 226) +++ trunk/tests/warnings/anon_no_return_value.js 2008-08-28 00:02:50 UTC (rev 227) @@ -9,10 +9,10 @@ var error2 = function(b) { if (b) { - return; + return; /*warning:anon_no_return_value*/ } else { - return ""; /*warning:anon_no_return_value*/ + return ""; } }; Modified: trunk/tests/warnings/missing_break.js =================================================================== --- trunk/tests/warnings/missing_break.js 2008-08-27 16:11:25 UTC (rev 226) +++ trunk/tests/warnings/missing_break.js 2008-08-28 00:02:50 UTC (rev 227) @@ -92,7 +92,13 @@ return i; } - default: + case 9: + /* test a break inside a loop */ + for (i = 0; i < 100; i++) { + break; + } + + default: /*warning:missing_break*/ break; } Modified: trunk/tests/warnings/no_return_value.js =================================================================== --- trunk/tests/warnings/no_return_value.js 2008-08-27 16:11:25 UTC (rev 226) +++ trunk/tests/warnings/no_return_value.js 2008-08-28 00:02:50 UTC (rev 227) @@ -9,10 +9,10 @@ function error2(b) { if (b) { - return; + return; /*warning:no_return_value*/ } else { - return ""; /*warning:no_return_value*/ + return ""; } } Modified: trunk/tests/warnings/unreachable_code.js =================================================================== --- trunk/tests/warnings/unreachable_code.js 2008-08-27 16:11:25 UTC (rev 226) +++ trunk/tests/warnings/unreachable_code.js 2008-08-28 00:02:50 UTC (rev 227) @@ -26,4 +26,16 @@ throw i; i -= 1; /*warning:unreachable_code*/ } + + function var_test() { + return undef; + var undef; + } + + function func_test() { + return fortytwo(); + function fortytwo() { + return 42; + } + } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mat...@us...> - 2008-08-28 00:14:17
|
Revision: 228 http://javascriptlint.svn.sourceforge.net/javascriptlint/?rev=228&view=rev Author: matthiasmiller Date: 2008-08-28 00:14:15 +0000 (Thu, 28 Aug 2008) Log Message: ----------- unreachable_code: check for unreachable conditions in for loops and do..while loops Modified Paths: -------------- trunk/pyjsl/warnings.py trunk/tests/warnings/missing_break.js trunk/tests/warnings/unreachable_code.js Modified: trunk/pyjsl/warnings.py =================================================================== --- trunk/pyjsl/warnings.py 2008-08-28 00:02:50 UTC (rev 227) +++ trunk/pyjsl/warnings.py 2008-08-28 00:14:15 UTC (rev 228) @@ -382,6 +382,23 @@ if not sibling.kind in (tok.VAR, tok.FUNCTION): raise LintWarning, sibling +@lookfor(tok.FOR) +def unreachable_code_(node): + # Warn if the for loop always exits. + preamble, code = node.kids + if preamble.kind == tok.RESERVED: + pre, condition, post = preamble.kids + if post: + if not None in _get_exit_points(code): + raise LintWarning, post + +@lookfor(tok.DO) +def unreachable_code__(node): + # Warn if the do..while loop always exits. + code, condition = node.kids + if not None in _get_exit_points(code): + raise LintWarning, condition + #TODO: @lookfor(tok.IF) def meaningless_block(node): condition, if_, else_ = node.kids Modified: trunk/tests/warnings/missing_break.js =================================================================== --- trunk/tests/warnings/missing_break.js 2008-08-28 00:02:50 UTC (rev 227) +++ trunk/tests/warnings/missing_break.js 2008-08-28 00:14:15 UTC (rev 228) @@ -94,7 +94,7 @@ case 9: /* test a break inside a loop */ - for (i = 0; i < 100; i++) { + for (;;) { break; } Modified: trunk/tests/warnings/unreachable_code.js =================================================================== --- trunk/tests/warnings/unreachable_code.js 2008-08-28 00:02:50 UTC (rev 227) +++ trunk/tests/warnings/unreachable_code.js 2008-08-28 00:14:15 UTC (rev 228) @@ -38,4 +38,27 @@ return 42; } } + + /* test unreachable statements in for loops */ + for (i = 0; i < 10; i++) { /*warning:unreachable_code*/ + if (i) + break; + else + return; + } + for (i = 0; i < 10; ) { + if (i) + break; + else + return; + } + + /* test unreachable statements in do..while loops. */ + do { + if (i) + break; + else + return; + } while (i); /*warning:unreachable_code*/ + } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mat...@us...> - 2008-08-28 04:34:13
|
Revision: 231 http://javascriptlint.svn.sourceforge.net/javascriptlint/?rev=231&view=rev Author: matthiasmiller Date: 2008-08-28 04:34:11 +0000 (Thu, 28 Aug 2008) Log Message: ----------- allow adjusting node positions when parsing scripts Modified Paths: -------------- trunk/pyjsl/jsparse.py trunk/pyspidermonkey/pyspidermonkey.c Modified: trunk/pyjsl/jsparse.py =================================================================== --- trunk/pyjsl/jsparse.py 2008-08-28 00:25:42 UTC (rev 230) +++ trunk/pyjsl/jsparse.py 2008-08-28 04:34:11 UTC (rev 231) @@ -151,7 +151,7 @@ opcode = 'JSOP_CPP_COMMENT' opcode = opcode[5:].lower() - start_offset = match.start()+1 + start_offset = match.start() end_offset = match.end() # Make sure it doesn't start in a string or regexp @@ -177,15 +177,27 @@ else: pos = match.start()+1 -def parse(script, error_callback): +def parse(script, error_callback, startpos=None): + """ All node positions will be relative to startpos. This allows scripts + to be embedded in a file (for example, HTML). + """ def _wrapped_callback(line, col, msg): assert msg.startswith('JSMSG_') msg = msg[6:].lower() error_callback(line, col, msg) - return pyspidermonkey.parse(script, _Node, _wrapped_callback) + startpos = startpos or NodePos(0,0) + return pyspidermonkey.parse(script, _Node, _wrapped_callback, + startpos.line, startpos.col) -def parsecomments(script, root_node): +def parsecomments(script, root_node, startpos=None): + """ All node positions will be relative to startpos. This allows scripts + to be embedded in a file (for example, HTML). + """ + # Use dummy text to rebase node positions. + if startpos: + script = ('\n' * startpos.line) + (' ' * startpos.col) + script + positions = NodePositions(script) comment_ignore_ranges = NodeRanges() @@ -195,7 +207,7 @@ elif node.kind == tok.STRING or \ (node.kind == tok.OBJECT and node.opcode == op.REGEXP): start_offset = positions.to_offset(node.start_pos()) - end_offset = positions.to_offset(node.end_pos()) + end_offset = positions.to_offset(node.end_pos()) - 1 comment_ignore_ranges.add(start_offset, end_offset) for kid in node.kids: if kid: @@ -324,6 +336,45 @@ for text, result in tests: self.assertEquals(is_compilable_unit(text), result) +class TestLineOffset(unittest.TestCase): + def testErrorPos(self): + def geterror(script, startpos): + errors = [] + def onerror(line, col, msg): + errors.append((line, col, msg)) + parse(script, onerror, startpos) + self.assertEquals(len(errors), 1) + return errors[0] + self.assertEquals(geterror(' ?', None), (0, 1, 'syntax_error')) + self.assertEquals(geterror('\n ?', None), (1, 1, 'syntax_error')) + self.assertEquals(geterror(' ?', NodePos(1,1)), (1, 2, 'syntax_error')) + self.assertEquals(geterror('\n ?', NodePos(1,1)), (2, 1, 'syntax_error')) + def testNodePos(self): + def getnodepos(script, startpos): + root = parse(script, None, startpos) + self.assertEquals(root.kind, tok.LC) + var, = root.kids + self.assertEquals(var.kind, tok.VAR) + return var.start_pos() + self.assertEquals(getnodepos('var x;', None), NodePos(0,0)) + self.assertEquals(getnodepos(' var x;', None), NodePos(0,1)) + self.assertEquals(getnodepos('\n\n var x;', None), NodePos(2,1)) + self.assertEquals(getnodepos('var x;', NodePos(3,4)), NodePos(3,4)) + self.assertEquals(getnodepos(' var x;', NodePos(3,4)), NodePos(3,5)) + self.assertEquals(getnodepos('\n\n var x;', NodePos(3,4)), NodePos(5,1)) + def testComments(self): + def testcomment(comment, startpos, expectedpos): + root = parse(comment, None, startpos) + comment, = parsecomments(comment, root, startpos) + self.assertEquals(comment.start_pos(), expectedpos) + for comment in ('/*comment*/', '//comment'): + testcomment(comment, None, NodePos(0,0)) + testcomment(' %s' % comment, None, NodePos(0,1)) + testcomment('\n\n %s' % comment, None, NodePos(2,1)) + testcomment('%s' % comment, NodePos(3,4), NodePos(3,4)) + testcomment(' %s' % comment, NodePos(3,4), NodePos(3,5)) + testcomment('\n\n %s' % comment, NodePos(3,4), NodePos(5,1)) + if __name__ == '__main__': unittest.main() Modified: trunk/pyspidermonkey/pyspidermonkey.c =================================================================== --- trunk/pyspidermonkey/pyspidermonkey.c 2008-08-28 00:25:42 UTC (rev 230) +++ trunk/pyspidermonkey/pyspidermonkey.c 2008-08-28 04:34:11 UTC (rev 231) @@ -124,17 +124,44 @@ typedef struct JSContextData { PyObject* node_class; PyObject* error_callback; + long int first_lineno; + long int first_index; } JSContextData; +static long int +to_pyjsl_lineno(JSContextData* data, long int lineno) { + /* SpiderMonkey uses 1-based line numbers. */ + return lineno + data->first_lineno - 1; +} + +static long int +to_pyjsl_index(JSContextData* data, long int lineno, long int index) { + /* SpiderMonkey uses 1-based line numbers. */ + if (lineno - 1 == 0) + return index + data->first_index; + else + return index; +} + +static JSTokenPtr +to_pyjsl_pos(JSContextData* data, JSTokenPtr ptr) { + JSTokenPtr newptr = ptr; + newptr.index = to_pyjsl_index(data, ptr.lineno, ptr.index); + newptr.lineno = to_pyjsl_lineno(data, ptr.lineno); + return newptr; +} + static void error_reporter(JSContext* cx, const char* message, JSErrorReport* report) { JSContextData* data = JS_GetContextPrivate(cx); - long int line = report->lineno - 1; + long int line = to_pyjsl_lineno(data, report->lineno); long int col = -1; - if (report->uclinebuf) + if (report->uclinebuf) { col = report->uctokenptr - report->uclinebuf; + col = to_pyjsl_index(data, report->lineno, col); + } // TODO: Check return value (void)PyObject_CallFunction(data->error_callback, "lls", @@ -169,6 +196,7 @@ JSContextData* data = JS_GetContextPrivate(context); PyObject* pynode = NULL; PyObject* kids = NULL; + JSTokenPtr tokenptr; /* TODO: make sure no tuple item already exists */ @@ -192,13 +220,15 @@ goto fail; /* pass the position */ - if (PyObject_SetAttrString(pynode, "_start_line", Py_BuildValue("i", jsnode->pn_pos.begin.lineno-1)) == -1) + tokenptr = to_pyjsl_pos(data, jsnode->pn_pos.begin); + if (PyObject_SetAttrString(pynode, "_start_line", Py_BuildValue("i", tokenptr.lineno)) == -1) goto fail; - if (PyObject_SetAttrString(pynode, "_start_col", Py_BuildValue("i", jsnode->pn_pos.begin.index)) == -1) + if (PyObject_SetAttrString(pynode, "_start_col", Py_BuildValue("i", tokenptr.index)) == -1) goto fail; - if (PyObject_SetAttrString(pynode, "_end_line", Py_BuildValue("i", jsnode->pn_pos.end.lineno-1)) == -1) + tokenptr = to_pyjsl_pos(data, jsnode->pn_pos.end); + if (PyObject_SetAttrString(pynode, "_end_line", Py_BuildValue("i", tokenptr.lineno)) == -1) goto fail; - if (PyObject_SetAttrString(pynode, "_end_col", Py_BuildValue("i", jsnode->pn_pos.end.index)) == -1) + if (PyObject_SetAttrString(pynode, "_end_col", Py_BuildValue("i", tokenptr.index)) == -1) goto fail; if ((jsnode->pn_type == TOK_NAME || jsnode->pn_type == TOK_DOT || @@ -370,8 +400,11 @@ error = "encountered an unknown error"; /* validate arguments */ - if (!PyArg_ParseTuple(args, "sOO", &m.script, &m.ctx_data.node_class, &m.ctx_data.error_callback)) + if (!PyArg_ParseTuple(args, "sOOll", &m.script, &m.ctx_data.node_class, + &m.ctx_data.error_callback, &m.ctx_data.first_lineno, + &m.ctx_data.first_index)) { return NULL; + } if (!PyCallable_Check(m.ctx_data.node_class)) { PyErr_SetString(PyExc_ValueError, "\"node_class\" must be callable"); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
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. |
From: <mat...@us...> - 2008-08-28 14:27:11
|
Revision: 233 http://javascriptlint.svn.sourceforge.net/javascriptlint/?rev=233&view=rev Author: matthiasmiller Date: 2008-08-28 14:27:08 +0000 (Thu, 28 Aug 2008) Log Message: ----------- no_return_value: fix for if statements with else Modified Paths: -------------- trunk/pyjsl/warnings.py trunk/tests/warnings/no_return_value.js Modified: trunk/pyjsl/warnings.py =================================================================== --- trunk/pyjsl/warnings.py 2008-08-28 04:58:29 UTC (rev 232) +++ trunk/pyjsl/warnings.py 2008-08-28 14:27:08 UTC (rev 233) @@ -118,6 +118,8 @@ exit_points = _get_exit_points(if_) if else_: exit_points |= _get_exit_points(else_) + else: + exit_points.add(None) elif node.kind == tok.SWITCH: exit_points = set([None]) Modified: trunk/tests/warnings/no_return_value.js =================================================================== --- trunk/tests/warnings/no_return_value.js 2008-08-28 04:58:29 UTC (rev 232) +++ trunk/tests/warnings/no_return_value.js 2008-08-28 14:27:08 UTC (rev 233) @@ -16,6 +16,12 @@ } } + function error3(b) { /*warning:no_return_value*/ + if (b) { + return ""; + } + } + function correct(b) { if (b) return; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mat...@us...> - 2009-03-03 17:03:09
|
Revision: 238 http://javascriptlint.svn.sourceforge.net/javascriptlint/?rev=238&view=rev Author: matthiasmiller Date: 2009-03-03 17:02:59 +0000 (Tue, 03 Mar 2009) Log Message: ----------- missing_semicolon: implement the missing semicolon warning This is not the most elegant solution, but it requires the least invasive changes to spidermonkey. Modified Paths: -------------- trunk/pyjsl/jsparse.py trunk/pyjsl/lint.py trunk/pyjsl/warnings.py trunk/pyspidermonkey/pyspidermonkey.c trunk/spidermonkey/src/jsparse.c trunk/spidermonkey/src/jsparse.h trunk/test.py trunk/tests/control_comments/declare.js trunk/tests/warnings/missing_semicolon.js trunk/tests/warnings/unreferenced_identifier.js Added Paths: ----------- trunk/tests/warnings/missing_semicolon_for_lambda.js Removed Paths: ------------- trunk/tests/conf/lambda_assign_requires_semicolon.js Modified: trunk/pyjsl/jsparse.py =================================================================== --- trunk/pyjsl/jsparse.py 2008-09-01 15:57:37 UTC (rev 237) +++ trunk/pyjsl/jsparse.py 2009-03-03 17:02:59 UTC (rev 238) @@ -253,6 +253,9 @@ if hasattr(node, 'atom'): print ' '*depth, print 'atom: %s' % node.atom + if node.no_semi: + print ' '*depth, + print '(no semicolon)' print for node in node.kids: _dump_node(node, depth+1) Modified: trunk/pyjsl/lint.py =================================================================== --- trunk/pyjsl/lint.py 2008-09-01 15:57:37 UTC (rev 237) +++ trunk/pyjsl/lint.py 2009-03-03 17:02:59 UTC (rev 238) @@ -376,7 +376,13 @@ def _lint_script_parts(script_parts, script_cache, lint_error, conf, import_callback): def report_lint(node, errname): - _report(node.start_pos(), errname, True) + # TODO: This is ugly hardcoding to improve the error positioning of + # "missing_semicolon" errors. + if errname == 'missing_semicolon' or errname == 'missing_semicolon_for_lambda': + pos = node.end_pos() + else: + pos = node.start_pos() + _report(pos, errname, True) def report_native(pos, errname): _report(pos, errname, False) Modified: trunk/pyjsl/warnings.py =================================================================== --- trunk/pyjsl/warnings.py 2008-09-01 15:57:37 UTC (rev 237) +++ trunk/pyjsl/warnings.py 2009-03-03 17:02:59 UTC (rev 238) @@ -22,6 +22,24 @@ import visitation from pyspidermonkey import tok, op +_ALL_TOKENS = tuple(filter(lambda x: x != tok.EOF, tok.__dict__.values())) + +def _get_assigned_lambda(node): + """ Given a node "x = function() {}", returns "function() {}". + """ + value = None + if node.kind == tok.SEMI: + assign_node, = node.kids + if assign_node and assign_node.kind == tok.ASSIGN: + ignored, value = assign_node.kids + elif node.kind == tok.VAR: + variables = node.kids + if variables: + value, = variables[-1].kids + + if value and value.kind == tok.FUNCTION and value.opcode == op.ANONFUNOBJ: + return value + # TODO: document inspect, node:opcode, etc warnings = { @@ -63,6 +81,7 @@ 'var_hides_arg': 'variable {0} hides argument', 'duplicate_formal': 'TODO', 'missing_semicolon': 'missing semicolon', + 'missing_semicolon_for_lambda': 'missing semicolon for lambda assignment', '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', @@ -538,10 +557,21 @@ def duplicate_formal(node): pass -@lookfor() +@lookfor(*_ALL_TOKENS) def missing_semicolon(node): - pass + if node.no_semi: + if not _get_assigned_lambda(node): + raise LintWarning, node +@lookfor(*_ALL_TOKENS) +def missing_semicolon_for_lambda(node): + if node.no_semi: + # spidermonkey sometimes returns incorrect positions for var + # statements, so use the position of the lambda instead. + lambda_ = _get_assigned_lambda(node) + if lambda_: + raise LintWarning, lambda_ + @lookfor() def ambiguous_newline(node): pass Modified: trunk/pyspidermonkey/pyspidermonkey.c =================================================================== --- trunk/pyspidermonkey/pyspidermonkey.c 2008-09-01 15:57:37 UTC (rev 237) +++ trunk/pyspidermonkey/pyspidermonkey.c 2009-03-03 17:02:59 UTC (rev 238) @@ -303,6 +303,9 @@ goto fail; } + if (PyObject_SetAttrString(pynode, "no_semi", PyBool_FromLong(jsnode->pn_no_semi)) == -1) + goto fail; + switch (jsnode->pn_arity) { case PN_FUNC: kids = PyTuple_New(1); Modified: trunk/spidermonkey/src/jsparse.c =================================================================== --- trunk/spidermonkey/src/jsparse.c 2008-09-01 15:57:37 UTC (rev 237) +++ trunk/spidermonkey/src/jsparse.c 2009-03-03 17:02:59 UTC (rev 238) @@ -248,6 +248,7 @@ pn->pn_next = NULL; pn->pn_ts = ts; pn->pn_source = NULL; + pn->pn_no_semi = JS_FALSE; return pn; } @@ -324,6 +325,7 @@ pn->pn_next = NULL; pn->pn_ts = NULL; pn->pn_source = NULL; + pn->pn_no_semi = JS_FALSE; return pn; } @@ -2738,7 +2740,8 @@ * insertion after do-while. See the testcase and discussion in * http://bugzilla.mozilla.org/show_bug.cgi?id=238945. */ - (void) js_MatchToken(cx, ts, TOK_SEMI); + if (!js_MatchToken(cx, ts, TOK_SEMI)) + pn->pn_no_semi = JS_TRUE; return pn; } break; @@ -3476,6 +3479,8 @@ return NULL; pn->pn_type = TOK_SEMI; pn->pn_kid = NULL; + if (tt == TOK_EOL) + pn->pn_no_semi = JS_TRUE; return pn; #if JS_HAS_DEBUGGER_KEYWORD @@ -3588,7 +3593,8 @@ } } - (void) js_MatchToken(cx, ts, TOK_SEMI); + if (!js_MatchToken(cx, ts, TOK_SEMI)) + pn->pn_no_semi = JS_TRUE; return pn; } @@ -4311,6 +4317,7 @@ pn2->pn_next = NULL; pn2->pn_ts = ts; pn2->pn_source = NULL; + pn2->pn_no_semi = JS_FALSE; pn = pn2; } } Modified: trunk/spidermonkey/src/jsparse.h =================================================================== --- trunk/spidermonkey/src/jsparse.h 2008-09-01 15:57:37 UTC (rev 237) +++ trunk/spidermonkey/src/jsparse.h 2009-03-03 17:02:59 UTC (rev 238) @@ -317,6 +317,7 @@ JSParseNode *pn_next; /* to align dval and pn_u on RISCs */ JSTokenStream *pn_ts; /* token stream for error reports */ JSAtom *pn_source; /* saved source for decompilation */ + JSBool pn_no_semi; /* missing semicolon */ }; #define pn_funAtom pn_u.func.funAtom Modified: trunk/test.py =================================================================== --- trunk/test.py 2008-09-01 15:57:37 UTC (rev 237) +++ trunk/test.py 2009-03-03 17:02:59 UTC (rev 238) @@ -32,7 +32,6 @@ for warning in regexp.findall(lines[i]): # TODO: implement these unimpl_warnings = ('ambiguous_newline', 'dup_option_explicit', - 'missing_semicolon' ) if not warning in unimpl_warnings: warnings.append((i, warning)) Deleted: trunk/tests/conf/lambda_assign_requires_semicolon.js =================================================================== --- trunk/tests/conf/lambda_assign_requires_semicolon.js 2008-09-01 15:57:37 UTC (rev 237) +++ trunk/tests/conf/lambda_assign_requires_semicolon.js 2009-03-03 17:02:59 UTC (rev 238) @@ -1,43 +0,0 @@ -/*conf:-lambda_assign_requires_semicolon*/ - - -/* Test with a simple variable. */ -var x = function() { - return {}; -} -x(); - -var a, b = function() { }, c -b(); /*warning:missing_semicolon*/ -var d, e = function() { } -e(); - -var y; -y = function() { - return []; -} -y(); - -global = function() { - return null; -} -global(); - -function Foo() -{ - this.bar = 10; - - /* Test an assignment to a member. */ - this.setBar = function(bar) { - this.bar = bar; - } - - this.setBar(this.bar * 2); -} - -/* Test an assignment to a prototype. */ -Foo.prototype.getBar = function() { - return this.bar; -} - -var foo = new Foo(); Modified: trunk/tests/control_comments/declare.js =================================================================== --- trunk/tests/control_comments/declare.js 2008-09-01 15:57:37 UTC (rev 237) +++ trunk/tests/control_comments/declare.js 2009-03-03 17:02:59 UTC (rev 238) @@ -9,8 +9,8 @@ /*jsl:declare document*//*warning:redeclared_var*/ } -var i = 10 -/*jsl:declare sample*//*warning:missing_semicolon*/ +var i = 10 /*warning:missing_semicolon*/ +/*jsl:declare sample*/ /* declare was scoped */ window.alert('JavaScript Lint');/*warning:undeclared_identifier*/ Modified: trunk/tests/warnings/missing_semicolon.js =================================================================== --- trunk/tests/warnings/missing_semicolon.js 2008-09-01 15:57:37 UTC (rev 237) +++ trunk/tests/warnings/missing_semicolon.js 2009-03-03 17:02:59 UTC (rev 238) @@ -1,19 +1,23 @@ /*jsl:option explicit*/ + function missing_semicolon() { /* missing semicolon after return */ function MissingSemicolonOnReturnStatement() { - return 0 - } /*warning:missing_semicolon*/ + return 0 /*warning:missing_semicolon*/ + } + function MissingSemicolonOnReturnStatement2() { return 0 } /*warning:missing_semicolon*/ - /* missing semicolon after return */ /* missing semicolon after lambda */ function x() { - this.y = function() { return 0 } /*warning:missing_semicolon*/ - } /*warning:missing_semicolon*/ + this.y = function() { return 0; } /*warning:missing_semicolon_for_lambda*/ + } - /* missing semicolon after return */ /* missing semicolon after lambda */ x.prototype.z = function() { - return 1 - } /*warning:missing_semicolon*/ -} /*warning:missing_semicolon*/ + return 1; + } /*warning:missing_semicolon_for_lambda*/ + + do x++; + while (x < 10) /*warning:missing_semicolon*/ +} + Copied: trunk/tests/warnings/missing_semicolon_for_lambda.js (from rev 237, trunk/tests/conf/lambda_assign_requires_semicolon.js) =================================================================== --- trunk/tests/warnings/missing_semicolon_for_lambda.js (rev 0) +++ trunk/tests/warnings/missing_semicolon_for_lambda.js 2009-03-03 17:02:59 UTC (rev 238) @@ -0,0 +1,43 @@ +/*jsl:option explicit*/ +/*jsl:declare global*/ + +/* Test with a simple variable. */ +var x = function() { + return {}; +} /*warning:missing_semicolon_for_lambda*/ +x(); + +var a, b = function() { }, c /*warning:missing_semicolon*/ +b(); +var d, e = function() { } /*warning:missing_semicolon_for_lambda*/ +e(); + +var y; +y = function() { + return []; +} /*warning:missing_semicolon_for_lambda*/ +y(); + +global = function() { + return null; +} /*warning:missing_semicolon_for_lambda*/ +global(); + +function Foo() +{ + this.bar = 10; + + /* Test an assignment to a member. */ + this.setBar = function(bar) { + this.bar = bar; + } /*warning:missing_semicolon_for_lambda*/ + + this.setBar(this.bar * 2); +} + +/* Test an assignment to a prototype. */ +Foo.prototype.getBar = function() { + return this.bar; +} /*warning:missing_semicolon_for_lambda*/ + +var foo = new Foo(); Modified: trunk/tests/warnings/unreferenced_identifier.js =================================================================== --- trunk/tests/warnings/unreferenced_identifier.js 2008-09-01 15:57:37 UTC (rev 237) +++ trunk/tests/warnings/unreferenced_identifier.js 2009-03-03 17:02:59 UTC (rev 238) @@ -15,7 +15,7 @@ /* Test an unreferenced parameter. */ var z = new function(unreferenced_parm) { /*warning:unreferenced_identifier*/ - } + }; z.prop = 42; /* Test an unreferenced variable. */ @@ -80,7 +80,7 @@ function get_callback(parm) { return function() { return parm; - } + }; } return get_callback(42); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mat...@us...> - 2009-03-04 01:43:11
|
Revision: 239 http://javascriptlint.svn.sourceforge.net/javascriptlint/?rev=239&view=rev Author: matthiasmiller Date: 2009-03-04 01:41:05 +0000 (Wed, 04 Mar 2009) Log Message: ----------- document bug with </script> inside comment Modified Paths: -------------- trunk/pyjsl/jsparse.py trunk/tests/html/script_tag_in_js_literal.html Added Paths: ----------- trunk/tests/html/script_tag_in_js_comment.html Modified: trunk/pyjsl/jsparse.py =================================================================== --- trunk/pyjsl/jsparse.py 2009-03-03 17:02:59 UTC (rev 238) +++ trunk/pyjsl/jsparse.py 2009-03-04 01:41:05 UTC (rev 239) @@ -367,6 +367,8 @@ ) for text, result in tests: self.assertEquals(is_compilable_unit(text), result) + # NOTE: This seems like a bug. + self.assert_(is_compilable_unit("/* test")) class TestLineOffset(unittest.TestCase): def testErrorPos(self): Copied: trunk/tests/html/script_tag_in_js_comment.html (from rev 237, trunk/tests/html/script_tag_in_js_literal.html) =================================================================== --- trunk/tests/html/script_tag_in_js_comment.html (rev 0) +++ trunk/tests/html/script_tag_in_js_comment.html 2009-03-04 01:41:05 UTC (rev 239) @@ -0,0 +1,12 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN"> +<html> +<head> + <title>JavaScript Lint Test Page</title> + <script type="text/javascript"><!-- + /* alert the </script> end tag */ /*warning:unterminated_comment*/ + //--> + </script> +</head> +<body> +</body> +</html> Modified: trunk/tests/html/script_tag_in_js_literal.html =================================================================== --- trunk/tests/html/script_tag_in_js_literal.html 2009-03-03 17:02:59 UTC (rev 238) +++ trunk/tests/html/script_tag_in_js_literal.html 2009-03-04 01:41:05 UTC (rev 239) @@ -3,7 +3,7 @@ <head> <title>JavaScript Lint Test Page</title> <script type="text/javascript"><!-- - /* alert the </script> end tag */ + /*jsl:declare window*/ var x = "</script>"; window.alert(x); //--> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mat...@us...> - 2009-03-04 06:47:49
|
Revision: 240 http://javascriptlint.svn.sourceforge.net/javascriptlint/?rev=240&view=rev Author: matthiasmiller Date: 2009-03-04 06:47:42 +0000 (Wed, 04 Mar 2009) Log Message: ----------- start improving error descriptions Modified Paths: -------------- trunk/jsl.py trunk/pyjsl/lint.py trunk/test.py Modified: trunk/jsl.py =================================================================== --- trunk/jsl.py 2009-03-04 01:41:05 UTC (rev 239) +++ trunk/jsl.py 2009-03-04 06:47:42 UTC (rev 240) @@ -55,9 +55,9 @@ pyjsl.jsparse.dump_tree(script) def _lint(paths, conf): - def lint_error(path, line, col, errname): + def lint_error(path, line, col, errname, errdesc): _lint_results['warnings'] = _lint_results['warnings'] + 1 - print '%s(%i): %s' % (path, line+1, errname) + print '%s(%i): %s' % (path, line+1, errdesc) pyjsl.lint.lint_files(paths, lint_error, conf=conf) def _resolve_paths(path, recurse): Modified: trunk/pyjsl/lint.py =================================================================== --- trunk/pyjsl/lint.py 2009-03-04 01:41:05 UTC (rev 239) +++ trunk/pyjsl/lint.py 2009-03-04 06:47:42 UTC (rev 240) @@ -382,12 +382,14 @@ pos = node.end_pos() else: pos = node.start_pos() - _report(pos, errname, True) + errdesc = warnings.warnings[errname] + _report(pos, errname, errdesc, True) def report_native(pos, errname): - _report(pos, errname, False) + # TODO: Format the error. + _report(pos, errname, errname, False) - def _report(pos, errname, require_key): + def _report(pos, errname, errdesc, require_key): try: if not conf[errname]: return @@ -399,7 +401,7 @@ if pos >= start and pos <= end: return - return lint_error(pos.line, pos.col, errname) + return lint_error(pos.line, pos.col, errname, errdesc) for scriptpos, script in script_parts: ignores = [] Modified: trunk/test.py =================================================================== --- trunk/test.py 2009-03-04 01:41:05 UTC (rev 239) +++ trunk/test.py 2009-03-04 06:47:42 UTC (rev 240) @@ -44,7 +44,7 @@ unexpected_warnings = [] conf = _get_conf(script) - def lint_error(path, line, col, errname): + def lint_error(path, line, col, errname, errdesc): warning = (line, errname) # Bad hack to fix line numbers on ambiguous else statements This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mat...@us...> - 2009-03-04 06:52:40
|
Revision: 241 http://javascriptlint.svn.sourceforge.net/javascriptlint/?rev=241&view=rev Author: matthiasmiller Date: 2009-03-04 06:52:38 +0000 (Wed, 04 Mar 2009) Log Message: ----------- fix exception when importing a path using backslashes on a Unix environment Modified Paths: -------------- trunk/pyjsl/lint.py Added Paths: ----------- trunk/tests/control_comments/import-slashes.js Modified: trunk/pyjsl/lint.py =================================================================== --- trunk/pyjsl/lint.py 2009-03-04 06:47:42 UTC (rev 240) +++ trunk/pyjsl/lint.py 2009-03-04 06:52:38 UTC (rev 241) @@ -206,6 +206,9 @@ def lint_files(paths, lint_error, conf=conf.Conf()): def lint_file(path, kind): def import_script(import_path): + # The user can specify paths using backslashes (such as when + # linting Windows scripts on a posix environment. + import_path = import_path.replace('\\', os.sep) import_path = os.path.join(os.path.dirname(path), import_path) return lint_file(import_path, 'js') def _lint_error(*args): Added: trunk/tests/control_comments/import-slashes.js =================================================================== --- trunk/tests/control_comments/import-slashes.js (rev 0) +++ trunk/tests/control_comments/import-slashes.js 2009-03-04 06:52:38 UTC (rev 241) @@ -0,0 +1,5 @@ +/*jsl:option explicit*/ + +/* Try importing using backslashes instead of forward slashes. */ +/*jsl:import ..\control_comments\import-slashes.js */ + Property changes on: trunk/tests/control_comments/import-slashes.js ___________________________________________________________________ Added: svn:eol-style + native This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mat...@us...> - 2009-05-20 07:38:06
|
Revision: 243 http://javascriptlint.svn.sourceforge.net/javascriptlint/?rev=243&view=rev Author: matthiasmiller Date: 2009-05-20 07:37:57 +0000 (Wed, 20 May 2009) Log Message: ----------- support the output-format setting Modified Paths: -------------- trunk/DEVELOPMENT trunk/jsl.py trunk/pyjsl/conf.py trunk/pyjsl/util.py Modified: trunk/DEVELOPMENT =================================================================== --- trunk/DEVELOPMENT 2009-03-04 07:19:18 UTC (rev 242) +++ trunk/DEVELOPMENT 2009-05-20 07:37:57 UTC (rev 243) @@ -20,7 +20,7 @@ Use the following command to upgrade SpiderMonkey. Replace X.X.X with the version number. js-X.X.X is the directory containing the new version of SpiderMonkey. Use a relative path for pretty commit messages. - + svn_load_dirs.pl \ -t X.X.X \ -p svn_load_dirs.conf \ Modified: trunk/jsl.py =================================================================== --- trunk/jsl.py 2009-03-04 07:19:18 UTC (rev 242) +++ trunk/jsl.py 2009-05-20 07:37:57 UTC (rev 243) @@ -57,7 +57,8 @@ def _lint(paths, conf): def lint_error(path, line, col, errname, errdesc): _lint_results['warnings'] = _lint_results['warnings'] + 1 - print '%s(%i): %s' % (path, line+1, errdesc) + print pyjsl.util.format_error(conf['output-format'], path, line, col, + errname, errdesc) pyjsl.lint.lint_files(paths, lint_error, conf=conf) def _resolve_paths(path, recurse): Modified: trunk/pyjsl/conf.py =================================================================== --- trunk/pyjsl/conf.py 2009-03-04 07:19:18 UTC (rev 242) +++ trunk/pyjsl/conf.py 2009-05-20 07:37:57 UTC (rev 243) @@ -55,7 +55,7 @@ self._settings = { 'recurse': recurse, 'show_context': BooleanSetting(False), - 'output-format': StringSetting('TODO'), + 'output-format': StringSetting('__FILE__(__LINE__): __ERROR__'), 'lambda_assign_requires_semicolon': BooleanSetting(False), 'legacy_control_comments': BooleanSetting(True), 'jscript_function_extensions': BooleanSetting(False), Modified: trunk/pyjsl/util.py =================================================================== --- trunk/pyjsl/util.py 2009-03-04 07:19:18 UTC (rev 242) +++ trunk/pyjsl/util.py 2009-05-20 07:37:57 UTC (rev 243) @@ -9,6 +9,46 @@ def isidentifier(text): return _identifier.match(text) +def _encode_error_keyword(s): + s = s.replace('\\', '\\\\') + s = s.replace('"', '\\"') + s = s.replace("'", "\\'") + s = s.replace("\t", "\\t") + s = s.replace("\r", "\\r") + s = s.replace("\n", "\\n") + return s + +def format_error(output_format, path, line, col, errname, errdesc): + errprefix = 'warning' #TODO + replacements = { + '__FILE__': path, + '__FILENAME__': os.path.basename(path), + '__LINE__': str(line+1), + '__COL__': str(col), + '__ERROR__': '%s: %s' % (errprefix, errdesc), + '__ERROR_NAME__': errname, + '__ERROR_PREFIX__': errprefix, + '__ERROR_MSG__': errdesc, + '__ERROR_MSGENC__': errdesc, + } + + formatted_error = output_format + + # If the output format starts with encode:, all of the keywords should be + # encoded. + if formatted_error.startswith('encode:'): + formatted_error = formatted_error[len('encode:'):] + encoded_keywords = replacements.keys() + else: + encoded_keywords = ['__ERROR_MSGENC__'] + + for keyword in encoded_keywords: + replacements[keyword] = _encode_error_keyword(replacements[keyword]) + + regexp = '|'.join(replacements.keys()) + return re.sub(regexp, lambda match: replacements[match.group(0)], + formatted_error) + def readfile(path): file = codecs.open(path, 'r', 'utf-8') contents = file.read() @@ -30,6 +70,28 @@ assert isidentifier('a') assert isidentifier('$0') + def testEncodeKeyword(self): + self.assertEquals(_encode_error_keyword(r'normal text'), 'normal text') + self.assertEquals(_encode_error_keyword(r'a\b'), r'a\\b') + self.assertEquals(_encode_error_keyword(r"identifier's"), r"identifier\'s") + self.assertEquals(_encode_error_keyword(r'"i"'), r'\"i\"') + self.assertEquals(_encode_error_keyword('a\tb'), r'a\tb') + self.assertEquals(_encode_error_keyword('a\rb'), r'a\rb') + self.assertEquals(_encode_error_keyword('a\nb'), r'a\nb') + + def testFormattedError(self): + self.assertEquals(format_error('__FILE__', '__LINE__', 1, 2, 'name', 'desc'), + '__LINE__') + self.assertEquals(format_error('__FILE__', r'c:\my\file', 1, 2, 'name', 'desc'), + r'c:\my\file') + self.assertEquals(format_error('encode:__FILE__', r'c:\my\file', 1, 2, 'name', 'desc'), + r'c:\\my\\file') + self.assertEquals(format_error('__ERROR_MSGENC__', r'c:\my\file', 1, 2, 'name', r'a\b'), + r'a\\b') + self.assertEquals(format_error('encode:__ERROR_MSGENC__', r'c:\my\file', 1, 2, 'name', r'a\b'), + r'a\\b') + + if __name__ == '__main__': unittest.main() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mat...@us...> - 2009-08-27 16:45:44
|
Revision: 245 http://javascriptlint.svn.sourceforge.net/javascriptlint/?rev=245&view=rev Author: matthiasmiller Date: 2009-08-27 16:45:33 +0000 (Thu, 27 Aug 2009) Log Message: ----------- ambiguous_newline: remove for new Modified Paths: -------------- trunk/DEVELOPMENT trunk/test.py Removed Paths: ------------- trunk/tests/warnings/ambiguous_newline.js Modified: trunk/DEVELOPMENT =================================================================== --- trunk/DEVELOPMENT 2009-05-26 02:26:18 UTC (rev 244) +++ trunk/DEVELOPMENT 2009-08-27 16:45:33 UTC (rev 245) @@ -13,6 +13,7 @@ > implement semicolons warning > implement line break warning > add test for syntax error +> consider reimplementing abiguous_newline ** UPGRADING SPIDERMONKEY Modified: trunk/test.py =================================================================== --- trunk/test.py 2009-05-26 02:26:18 UTC (rev 244) +++ trunk/test.py 2009-08-27 16:45:33 UTC (rev 245) @@ -31,8 +31,7 @@ for i in range(0, len(lines)): for warning in regexp.findall(lines[i]): # TODO: implement these - unimpl_warnings = ('ambiguous_newline', 'dup_option_explicit', - ) + unimpl_warnings = ('dup_option_explicit',) if not warning in unimpl_warnings: warnings.append((i, warning)) return warnings Deleted: trunk/tests/warnings/ambiguous_newline.js =================================================================== --- trunk/tests/warnings/ambiguous_newline.js 2009-05-26 02:26:18 UTC (rev 244) +++ trunk/tests/warnings/ambiguous_newline.js 2009-08-27 16:45:33 UTC (rev 245) @@ -1,261 +0,0 @@ -/*jsl:option explicit*/ -function ambiguous_newline() { - /* the EOL test is based on JSLint's documentation */ - var a, b, i, o, s; - - /* legal: , */ - s = s.substr(0, - 1); - - /* legal: . */ - s = s. - substr(0, 1); - - /* legal: ; */ - s = s.substr(0, 1); - - /* legal: : */ - o = { test : - 'works' }; - - /* legal: { */ - /* legal: } */ - if (s) { - s = i; - } - - /* legal: ( */ - s = s.substr( - 0, 1); - - /* legal: [ */ - s = o[ - 'test']; - - /* legal: = */ - s = - '?'; - - /* legal: < */ - b = (i < - 14); - - /* legal: > */ - b = (i > - 93); - - /* legal: ? */ - i = (b ? - 1 : 0); - - /* legal: ! */ - b = (! - false); - - /* legal: + */ - i = 55 + - i; - - /* legal: - */ - i = 101 - - i; - - /* legal: * */ - i = i * - 2; - - /* legal: / */ - i = i / - 43; - - /* legal: % */ - i = i % - 16; - - /* legal: ~ */ - i = ~ - 16; - - /* legal: ^ */ - i = i ^ - 32; - - /* legal: | */ - i = i | - 64; - - /* legal: & */ - i = i & - 2; - - /* legal: == */ - b = (i == - 99); - - /* legal: != */ - b = (i != - -1); - - /* legal: <= */ - b = (i <= - 4); - - /* legal: >= */ - b = (i >= - 3.14); - - /* legal: += */ - i += - 1; - - /* legal: -= */ - i -= - 1; - - /* legal: *= */ - i *= - 19; - - /* legal: /= */ - i /= - 17; - - /* legal: %= */ - i %= - 15; - - /* legal: ^= */ - i ^= - 1024; - - /* legal: |= */ - i ^= - 512; - - /* legal: &= */ - i ^= - 256; - - /* legal: << */ - i = i << - 2; - - /* legal: >> */ - i = i >> - 1; - - /* legal: || */ - b = (b || - false); - - /* legal: && */ - b = (b && - true); - - /* legal: === */ - b = (i === - 0); - - /* legal: !== */ - b = (i !== - 0); - - /* legal: <<= */ - i <<= - 1; - - /* legal: >>= */ - i >>= - 2; - - /* legal: >>> */ - i = i >>> - 4; - - /* legal: >>>= */ - i >>>= - 2; - - /* legal */ - o = - { - 'component one': 1, - 'component two': 2 - }; - - /* legal */ - o = { - one: 1, - two: 2 - }; - - /* legal */ - i = o['one' - ]; - - /* illegal */ - i = o - ['one']; /*warning:ambiguous_newline*/ - - /* illegal: identifier */ - s = i - + "?"; /*warning:ambiguous_newline*/ - - /* illegal: string */ - s = "this " - + i; /*warning:ambiguous_newline*/ - - /* illegal: number */ - i = 14 - / 2; /*warning:ambiguous_newline*/ - - /* illegal: ) */ - b = (i == 7) - || false; /*warning:ambiguous_newline*/ - - /* illegal: ) */ - s = o['test'] - + "!"; /*warning:ambiguous_newline*/ - - /* illegal: ++ */ - b = i++ /*warning:inc_dec_within_stmt*/ - || true; /*warning:ambiguous_newline*/ - - /* illegal: -- */ - s = i-- /*warning:inc_dec_within_stmt*/ - + " = i"; /*warning:ambiguous_newline*/ - - /* legal */ - if (true) /*warning:meaningless_block*/ - { - i++; - } - else - { - i--; - } - while (false) - { - i--; - } - switch (1) - { - default: - break; - } - for (i = 0; i < 1; i++) - { - s = i + ""; - } - function Test() - { - return ""; - } - try - { - s = null; - } - catch (err) - { - } -} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mat...@us...> - 2009-10-03 09:53:20
|
Revision: 247 http://javascriptlint.svn.sourceforge.net/javascriptlint/?rev=247&view=rev Author: matthiasmiller Date: 2009-10-03 09:07:39 +0000 (Sat, 03 Oct 2009) Log Message: ----------- Make test.py a standalone script. Modified Paths: -------------- trunk/jsl.py trunk/setup.py trunk/test.py Property Changed: ---------------- trunk/test.py Modified: trunk/jsl.py =================================================================== --- trunk/jsl.py 2009-08-27 16:52:43 UTC (rev 246) +++ trunk/jsl.py 2009-10-03 09:07:39 UTC (rev 247) @@ -12,43 +12,18 @@ except ImportError: pass else: - sys.path.append(setup.get_lib_path()) + setup.addsearchpath() import pyjsl.conf import pyjsl.htmlparse import pyjsl.jsparse import pyjsl.util -import test _lint_results = { 'warnings': 0, 'errors': 0 } -def get_test_files(): - # Get a list of test files. - dir_ = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'tests') - - all_files = [] - for root, dirs, files in os.walk(dir_): - all_files += [os.path.join(dir_, root, file) for file in files] - if '.svn' in dirs: - dirs.remove('.svn') - # TODO - if 'conf' in dirs: - dirs.remove('conf') - all_files.sort() - return all_files - -def run_tests(): - for file in get_test_files(): - ext = os.path.splitext(file)[1] - if ext in ('.htm', '.html', '.js'): - try: - test.run(file) - except test.TestError, error: - print error - def _dump(paths): for path in paths: script = pyjsl.util.readfile(path) @@ -102,8 +77,6 @@ add = parser.add_option add("--conf", dest="conf", metavar="CONF", help="set the conf file") - add("-t", "--test", dest="test", action="store_true", default=False, - help="run the javascript tests") add("--profile", dest="profile", action="store_true", default=False, help="turn on hotshot profiling") add("--dump", dest="dump", action="store_true", default=False, @@ -137,9 +110,6 @@ runner = unittest.TextTestRunner(verbosity=options.verbosity) runner.run(suite) - if options.test: - profile_func(run_tests) - paths = [] for recurse, path in conf['paths']: paths.extend(_resolve_paths(path, recurse)) Modified: trunk/setup.py =================================================================== --- trunk/setup.py 2009-08-27 16:52:43 UTC (rev 246) +++ trunk/setup.py 2009-10-03 09:07:39 UTC (rev 247) @@ -2,6 +2,7 @@ # vim: ts=4 sw=4 expandtab from distutils.core import setup, Extension import os +import sys # Add the bin directory to the module search path def get_lib_path(): @@ -12,6 +13,9 @@ build.finalize_options() return os.path.join(os.path.dirname(__file__), build.build_platlib) +def addsearchpath(): + sys.path.append(get_lib_path()) + if __name__ == '__main__': if os.name == 'nt': library = 'js32' Modified: trunk/test.py =================================================================== --- trunk/test.py 2009-08-27 16:52:43 UTC (rev 246) +++ trunk/test.py 2009-10-03 09:07:39 UTC (rev 247) @@ -1,6 +1,16 @@ +#!/usr/bin/python # vim: ts=4 sw=4 expandtab +import os import re +import sys +try: + import setup +except ImportError: + pass +else: + setup.addsearchpath() + import pyjsl.conf import pyjsl.lint @@ -36,7 +46,7 @@ warnings.append((i, warning)) return warnings -def run(path): +def _testfile(path): # Parse the script and find the expected warnings. script = open(path).read() expected_warnings = _get_expected_warnings(script) @@ -70,3 +80,33 @@ if errors: raise TestError, '\n'.join(errors) +def _get_test_files(): + # Get a list of test files. + dir_ = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'tests') + + all_files = [] + for root, dirs, files in os.walk(dir_): + all_files += [os.path.join(dir_, root, file) for file in files] + if '.svn' in dirs: + dirs.remove('.svn') + # TODO + if 'conf' in dirs: + dirs.remove('conf') + all_files.sort() + return all_files + +def main(): + haderrors = False + for file in _get_test_files(): + ext = os.path.splitext(file)[1] + if ext in ('.htm', '.html', '.js'): + try: + _testfile(file) + except test.TestError, error: + haderrors = True + print error + sys.exit(haderrors) + +if __name__ == '__main__': + main() + Property changes on: trunk/test.py ___________________________________________________________________ Added: svn:executable + * This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mat...@us...> - 2009-10-03 15:04:32
|
Revision: 249 http://javascriptlint.svn.sourceforge.net/javascriptlint/?rev=249&view=rev Author: matthiasmiller Date: 2009-10-03 15:04:25 +0000 (Sat, 03 Oct 2009) Log Message: ----------- Use a different approach to allow pyspidermonkey to be used from the trunk tree. Modified Paths: -------------- trunk/jsl.py trunk/pyjsl/jsparse.py trunk/pyjsl/lint.py trunk/pyjsl/warnings.py trunk/setup.py trunk/test.py Added Paths: ----------- trunk/pyjsl/spidermonkey.py trunk/pyjsl/spidermonkey_.py Modified: trunk/jsl.py =================================================================== --- trunk/jsl.py 2009-10-03 09:35:59 UTC (rev 248) +++ trunk/jsl.py 2009-10-03 15:04:25 UTC (rev 249) @@ -7,13 +7,6 @@ import unittest from optparse import OptionParser -try: - import setup -except ImportError: - pass -else: - setup.addsearchpath() - import pyjsl.conf import pyjsl.htmlparse import pyjsl.jsparse Modified: trunk/pyjsl/jsparse.py =================================================================== --- trunk/pyjsl/jsparse.py 2009-10-03 09:35:59 UTC (rev 248) +++ trunk/pyjsl/jsparse.py 2009-10-03 15:04:25 UTC (rev 249) @@ -5,8 +5,8 @@ import re import unittest -import pyspidermonkey -from pyspidermonkey import tok, op +import spidermonkey +from spidermonkey import tok, op _tok_names = dict(zip( [getattr(tok, prop) for prop in dir(tok)], @@ -17,7 +17,7 @@ ['op.%s' % prop for prop in dir(op)] )) -NodePos = pyspidermonkey.NodePos +NodePos = spidermonkey.NodePos class NodePositions: " Given a string, allows [x] lookups for NodePos line and column numbers." @@ -203,8 +203,8 @@ error_callback(line, col, msg) startpos = startpos or NodePos(0,0) - return pyspidermonkey.parse(script, _Node, _wrapped_callback, - startpos.line, startpos.col) + return spidermonkey.parse(script, _Node, _wrapped_callback, + startpos.line, startpos.col) def filtercomments(possible_comments, node_positions, root_node): comment_ignore_ranges = NodeRanges() @@ -238,7 +238,7 @@ return filtercomments(possible_comments, node_positions, root_node) def is_compilable_unit(script): - return pyspidermonkey.is_compilable_unit(script) + return spidermonkey.is_compilable_unit(script) def _dump_node(node, depth=0): if node is None: Modified: trunk/pyjsl/lint.py =================================================================== --- trunk/pyjsl/lint.py 2009-10-03 09:35:59 UTC (rev 248) +++ trunk/pyjsl/lint.py 2009-10-03 15:04:25 UTC (rev 249) @@ -10,7 +10,7 @@ import warnings import util -from pyspidermonkey import tok, op +from spidermonkey import tok, op _newline_kinds = ( 'eof', 'comma', 'dot', 'semi', 'colon', 'lc', 'rc', 'lp', 'rb', 'assign', Added: trunk/pyjsl/spidermonkey.py =================================================================== --- trunk/pyjsl/spidermonkey.py (rev 0) +++ trunk/pyjsl/spidermonkey.py 2009-10-03 15:04:25 UTC (rev 249) @@ -0,0 +1,10 @@ +# vim: ts=4 sw=4 expandtab + +# This is a wrapper script to make it easier for development. It tries to +# import the development version first, and if that fails, it goes after the +# real version. +try: + from spidermonkey_ import * +except ImportError: + from pyspidermonkey import * + Property changes on: trunk/pyjsl/spidermonkey.py ___________________________________________________________________ Added: svn:eol-style + native Added: trunk/pyjsl/spidermonkey_.py =================================================================== --- trunk/pyjsl/spidermonkey_.py (rev 0) +++ trunk/pyjsl/spidermonkey_.py 2009-10-03 15:04:25 UTC (rev 249) @@ -0,0 +1,20 @@ +# vim: ts=4 sw=4 expandtab +from distutils.core import setup, Extension +import os +import sys + +# Add the bin directory to the module search path +def _get_lib_path(): + import distutils.dist + import distutils.command.build + dist = distutils.dist.Distribution() + build = distutils.command.build.build(dist) + build.finalize_options() + return os.path.join(os.path.dirname(__file__), '..', build.build_platlib) + +sys.path.insert(0, _get_lib_path()) +try: + from pyspidermonkey import * +finally: + sys.path.pop(0) + Property changes on: trunk/pyjsl/spidermonkey_.py ___________________________________________________________________ Added: svn:eol-style + native Modified: trunk/pyjsl/warnings.py =================================================================== --- trunk/pyjsl/warnings.py 2009-10-03 09:35:59 UTC (rev 248) +++ trunk/pyjsl/warnings.py 2009-10-03 15:04:25 UTC (rev 249) @@ -20,8 +20,9 @@ import util import visitation -from pyspidermonkey import tok, op +from spidermonkey import tok, op + _ALL_TOKENS = tuple(filter(lambda x: x != tok.EOF, tok.__dict__.values())) def _get_assigned_lambda(node): Modified: trunk/setup.py =================================================================== --- trunk/setup.py 2009-10-03 09:35:59 UTC (rev 248) +++ trunk/setup.py 2009-10-03 15:04:25 UTC (rev 249) @@ -4,18 +4,6 @@ import os import sys -# Add the bin directory to the module search path -def get_lib_path(): - import distutils.dist - import distutils.command.build - dist = distutils.dist.Distribution() - build = distutils.command.build.build(dist) - build.finalize_options() - return os.path.join(os.path.dirname(__file__), build.build_platlib) - -def addsearchpath(): - sys.path.append(get_lib_path()) - if __name__ == '__main__': if os.name == 'nt': library = 'js32' @@ -50,7 +38,7 @@ console = ['jsl.py'], options = { 'py2exe': { - 'excludes': 'setup', + 'excludes': ['pyjsl.spidermonkey_'], 'bundle_files': 1 } }, Modified: trunk/test.py =================================================================== --- trunk/test.py 2009-10-03 09:35:59 UTC (rev 248) +++ trunk/test.py 2009-10-03 15:04:25 UTC (rev 249) @@ -4,13 +4,6 @@ import re import sys -try: - import setup -except ImportError: - pass -else: - setup.addsearchpath() - import pyjsl.conf import pyjsl.lint @@ -102,7 +95,7 @@ if ext in ('.htm', '.html', '.js'): try: _testfile(file) - except test.TestError, error: + except TestError, error: haderrors = True print error sys.exit(haderrors) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mat...@us...> - 2009-10-03 15:33:45
|
Revision: 251 http://javascriptlint.svn.sourceforge.net/javascriptlint/?rev=251&view=rev Author: matthiasmiller Date: 2009-10-03 15:33:38 +0000 (Sat, 03 Oct 2009) Log Message: ----------- Move jsl into a javascriptlint subdirectory. Modified Paths: -------------- trunk/test.py Added Paths: ----------- trunk/javascriptlint/ trunk/javascriptlint/__init__.py trunk/javascriptlint/jsl.py trunk/javascriptlint/pyjsl/ trunk/javascriptlint/pyspidermonkey/ Removed Paths: ------------- trunk/jsl.py trunk/pyjsl/ trunk/pyspidermonkey/ Property changes on: trunk/javascriptlint ___________________________________________________________________ Added: svn:ignore + *.pyc Property changes on: trunk/javascriptlint/__init__.py ___________________________________________________________________ Added: svn:eol-style + native Copied: trunk/javascriptlint/jsl.py (from rev 250, trunk/jsl.py) =================================================================== --- trunk/javascriptlint/jsl.py (rev 0) +++ trunk/javascriptlint/jsl.py 2009-10-03 15:33:38 UTC (rev 251) @@ -0,0 +1,125 @@ +#!/usr/bin/python +# vim: ts=4 sw=4 expandtab +import codecs +import glob +import os +import sys +import unittest +from optparse import OptionParser + +import pyjsl.conf +import pyjsl.htmlparse +import pyjsl.jsparse +import pyjsl.lint +import pyjsl.util + +_lint_results = { + 'warnings': 0, + 'errors': 0 +} + +def _dump(paths): + for path in paths: + script = pyjsl.util.readfile(path) + pyjsl.jsparse.dump_tree(script) + +def _lint(paths, conf): + def lint_error(path, line, col, errname, errdesc): + _lint_results['warnings'] = _lint_results['warnings'] + 1 + print pyjsl.util.format_error(conf['output-format'], path, line, col, + errname, errdesc) + pyjsl.lint.lint_files(paths, lint_error, conf=conf) + +def _resolve_paths(path, recurse): + if os.path.isfile(path): + return [path] + elif os.path.isdir(path): + dir = path + pattern = '*' + else: + dir, pattern = os.path.split(path) + + # Build a list of directories + dirs = [dir] + if recurse: + for cur_root, cur_dirs, cur_files in os.walk(dir): + for name in cur_dirs: + dirs.append(os.path.join(cur_root, name)) + + # Glob all files. + paths = [] + for dir in dirs: + paths.extend(glob.glob(os.path.join(dir, pattern))) + return paths + +def _profile_enabled(func, *args, **kwargs): + import tempfile + import hotshot + import hotshot.stats + handle, filename = tempfile.mkstemp() + profile = hotshot.Profile(filename) + profile.runcall(func, *args, **kwargs) + profile.close() + stats = hotshot.stats.load(filename) + stats = stats.sort_stats("time") + stats.print_stats() +def _profile_disabled(func, *args, **kwargs): + func(*args, **kwargs) + +def main(): + parser = OptionParser(usage="%prog [options] [files]") + add = parser.add_option + add("--conf", dest="conf", metavar="CONF", + help="set the conf file") + add("--profile", dest="profile", action="store_true", default=False, + help="turn on hotshot profiling") + add("--dump", dest="dump", action="store_true", default=False, + help="dump this script") + add("--unittest", dest="unittest", action="store_true", default=False, + help="run the python unittests") + add("--quiet", dest="verbosity", action="store_const", const=0, + help="minimal output") + add("--verbose", dest="verbosity", action="store_const", const=2, + help="verbose output") + parser.set_defaults(verbosity=1) + options, args = parser.parse_args() + + if len(sys.argv) == 1: + parser.print_help() + sys.exit() + + conf = pyjsl.conf.Conf() + if options.conf: + conf.loadfile(options.conf) + + profile_func = _profile_disabled + if options.profile: + profile_func = _profile_enabled + + if options.unittest: + suite = unittest.TestSuite(); + for module in [pyjsl.htmlparse, pyjsl.jsparse, pyjsl.util]: + suite.addTest(unittest.findTestCases(module)) + + runner = unittest.TextTestRunner(verbosity=options.verbosity) + runner.run(suite) + + paths = [] + for recurse, path in conf['paths']: + paths.extend(_resolve_paths(path, recurse)) + for arg in args: + paths.extend(_resolve_paths(arg, False)) + if options.dump: + profile_func(_dump, paths) + else: + profile_func(_lint, paths, conf) + + if _lint_results['errors']: + sys.exit(3) + if _lint_results['warnings']: + sys.exit(1) + sys.exit(1) + +if __name__ == '__main__': + main() + Property changes on: trunk/javascriptlint/jsl.py ___________________________________________________________________ Added: svn:executable + * Added: svn:mergeinfo + Added: svn:eol-style + native Property changes on: trunk/javascriptlint/pyjsl ___________________________________________________________________ Added: svn:ignore + *.pyc Added: svn:mergeinfo + Property changes on: trunk/javascriptlint/pyspidermonkey ___________________________________________________________________ Added: svn:mergeinfo + Deleted: trunk/jsl.py =================================================================== --- trunk/jsl.py 2009-10-03 15:11:21 UTC (rev 250) +++ trunk/jsl.py 2009-10-03 15:33:38 UTC (rev 251) @@ -1,125 +0,0 @@ -#!/usr/bin/python -# vim: ts=4 sw=4 expandtab -import codecs -import glob -import os -import sys -import unittest -from optparse import OptionParser - -import pyjsl.conf -import pyjsl.htmlparse -import pyjsl.jsparse -import pyjsl.lint -import pyjsl.util - -_lint_results = { - 'warnings': 0, - 'errors': 0 -} - -def _dump(paths): - for path in paths: - script = pyjsl.util.readfile(path) - pyjsl.jsparse.dump_tree(script) - -def _lint(paths, conf): - def lint_error(path, line, col, errname, errdesc): - _lint_results['warnings'] = _lint_results['warnings'] + 1 - print pyjsl.util.format_error(conf['output-format'], path, line, col, - errname, errdesc) - pyjsl.lint.lint_files(paths, lint_error, conf=conf) - -def _resolve_paths(path, recurse): - if os.path.isfile(path): - return [path] - elif os.path.isdir(path): - dir = path - pattern = '*' - else: - dir, pattern = os.path.split(path) - - # Build a list of directories - dirs = [dir] - if recurse: - for cur_root, cur_dirs, cur_files in os.walk(dir): - for name in cur_dirs: - dirs.append(os.path.join(cur_root, name)) - - # Glob all files. - paths = [] - for dir in dirs: - paths.extend(glob.glob(os.path.join(dir, pattern))) - return paths - -def _profile_enabled(func, *args, **kwargs): - import tempfile - import hotshot - import hotshot.stats - handle, filename = tempfile.mkstemp() - profile = hotshot.Profile(filename) - profile.runcall(func, *args, **kwargs) - profile.close() - stats = hotshot.stats.load(filename) - stats = stats.sort_stats("time") - stats.print_stats() -def _profile_disabled(func, *args, **kwargs): - func(*args, **kwargs) - -def main(): - parser = OptionParser(usage="%prog [options] [files]") - add = parser.add_option - add("--conf", dest="conf", metavar="CONF", - help="set the conf file") - add("--profile", dest="profile", action="store_true", default=False, - help="turn on hotshot profiling") - add("--dump", dest="dump", action="store_true", default=False, - help="dump this script") - add("--unittest", dest="unittest", action="store_true", default=False, - help="run the python unittests") - add("--quiet", dest="verbosity", action="store_const", const=0, - help="minimal output") - add("--verbose", dest="verbosity", action="store_const", const=2, - help="verbose output") - parser.set_defaults(verbosity=1) - options, args = parser.parse_args() - - if len(sys.argv) == 1: - parser.print_help() - sys.exit() - - conf = pyjsl.conf.Conf() - if options.conf: - conf.loadfile(options.conf) - - profile_func = _profile_disabled - if options.profile: - profile_func = _profile_enabled - - if options.unittest: - suite = unittest.TestSuite(); - for module in [pyjsl.htmlparse, pyjsl.jsparse, pyjsl.util]: - suite.addTest(unittest.findTestCases(module)) - - runner = unittest.TextTestRunner(verbosity=options.verbosity) - runner.run(suite) - - paths = [] - for recurse, path in conf['paths']: - paths.extend(_resolve_paths(path, recurse)) - for arg in args: - paths.extend(_resolve_paths(arg, False)) - if options.dump: - profile_func(_dump, paths) - else: - profile_func(_lint, paths, conf) - - if _lint_results['errors']: - sys.exit(3) - if _lint_results['warnings']: - sys.exit(1) - sys.exit(1) - -if __name__ == '__main__': - main() - Modified: trunk/test.py =================================================================== --- trunk/test.py 2009-10-03 15:11:21 UTC (rev 250) +++ trunk/test.py 2009-10-03 15:33:38 UTC (rev 251) @@ -4,8 +4,8 @@ import re import sys -import pyjsl.conf -import pyjsl.lint +import javascriptlint.pyjsl.conf +import javascriptlint.pyjsl.lint _DEFAULT_CONF = """ # This warning triggers a lot of warnings in many of the tests, so only enable @@ -19,7 +19,7 @@ def _get_conf(script): regexp = re.compile(r"/\*conf:([^*]*)\*/") text = '\n'.join(regexp.findall(script)) - conf = pyjsl.conf.Conf() + conf = javascriptlint.pyjsl.conf.Conf() conf.loadtext(_DEFAULT_CONF) conf.loadtext(text) return conf @@ -59,7 +59,7 @@ else: unexpected_warnings.append(warning) - pyjsl.lint.lint_files([path], lint_error, conf=conf) + javascriptlint.pyjsl.lint.lint_files([path], lint_error, conf=conf) errors = [] if expected_warnings: This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mat...@us...> - 2009-10-03 15:45:29
|
Revision: 253 http://javascriptlint.svn.sourceforge.net/javascriptlint/?rev=253&view=rev Author: matthiasmiller Date: 2009-10-03 15:45:19 +0000 (Sat, 03 Oct 2009) Log Message: ----------- Create a wrapper script to run jsl to make this Unix-friendly. Modified Paths: -------------- trunk/javascriptlint/__init__.py trunk/setup.py Added Paths: ----------- trunk/jsl Modified: trunk/javascriptlint/__init__.py =================================================================== --- trunk/javascriptlint/__init__.py 2009-10-03 15:41:59 UTC (rev 252) +++ trunk/javascriptlint/__init__.py 2009-10-03 15:45:19 UTC (rev 253) @@ -0,0 +1,3 @@ +# vim: ts=4 sw=4 expandtab +from jsl import main + Added: trunk/jsl =================================================================== --- trunk/jsl (rev 0) +++ trunk/jsl 2009-10-03 15:45:19 UTC (rev 253) @@ -0,0 +1,5 @@ +#!/usr/bin/python +# vim: ts=4 sw=4 expandtab +import javascriptlint +javascriptlint.main() + Property changes on: trunk/jsl ___________________________________________________________________ Added: svn:executable + * Added: svn:eol-style + native Modified: trunk/setup.py =================================================================== --- trunk/setup.py 2009-10-03 15:41:59 UTC (rev 252) +++ trunk/setup.py 2009-10-03 15:45:19 UTC (rev 253) @@ -10,24 +10,26 @@ else: library = 'js' pyspidermonkey = Extension( - 'pyspidermonkey', + 'javascriptlint.pyspidermonkey', include_dirs = ['spidermonkey/src', 'build/spidermonkey'], library_dirs = ['build/spidermonkey'], libraries = [library], sources = [ - 'pyspidermonkey/pyspidermonkey.c', - 'pyspidermonkey/nodepos.c' + 'javascriptlint/pyspidermonkey/pyspidermonkey.c', + 'javascriptlint/pyspidermonkey/nodepos.c' ] ) args = {} args.update( - name = 'pyjsl', + name = 'javascriptlint', version = '1.0', author = 'Matthias Miller', author_email = 'in...@ja...', url = 'http://www.javascriptlint.com/', description = 'JavaScript Lint', - ext_modules = [pyspidermonkey] + ext_modules = [pyspidermonkey], + packages = ['javascriptlint', 'javascriptlint.pyjsl'], + scripts = ['jsl'] ) try: import py2exe This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |