javascriptlint-commit Mailing List for JavaScript Lint (Page 7)
Status: Beta
Brought to you by:
matthiasmiller
You can subscribe to this list here.
| 2008 |
Jan
|
Feb
|
Mar
(42) |
Apr
(15) |
May
(2) |
Jun
|
Jul
|
Aug
(33) |
Sep
(3) |
Oct
|
Nov
|
Dec
|
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2009 |
Jan
|
Feb
|
Mar
(5) |
Apr
|
May
(2) |
Jun
|
Jul
|
Aug
(2) |
Sep
|
Oct
(43) |
Nov
(4) |
Dec
(1) |
| 2010 |
Jan
|
Feb
|
Mar
|
Apr
(6) |
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(1) |
Nov
|
Dec
|
| 2011 |
Jan
|
Feb
|
Mar
|
Apr
(1) |
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(1) |
| 2013 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
(20) |
Oct
(23) |
Nov
|
Dec
(1) |
| 2014 |
Jan
(1) |
Feb
(2) |
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(4) |
Nov
|
Dec
|
| 2016 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(18) |
| 2018 |
Jan
(7) |
Feb
|
Mar
|
Apr
|
May
|
Jun
(8) |
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
|
From: <mat...@us...> - 2008-09-01 15:57:39
|
Revision: 237
http://javascriptlint.svn.sourceforge.net/javascriptlint/?rev=237&view=rev
Author: matthiasmiller
Date: 2008-09-01 15:57:37 +0000 (Mon, 01 Sep 2008)
Log Message:
-----------
fix for Python 2.4
Modified Paths:
--------------
trunk/pyjsl/warnings.py
Modified: trunk/pyjsl/warnings.py
===================================================================
--- trunk/pyjsl/warnings.py 2008-09-01 14:04:10 UTC (rev 236)
+++ trunk/pyjsl/warnings.py 2008-09-01 15:57:37 UTC (rev 237)
@@ -138,8 +138,10 @@
exit_points.remove(None)
# Convert "break" into None
- exit_points = set(map(lambda node: node \
- if node and node.kind != tok.BREAK else None, exit_points))
+ def break_to_none(node):
+ if node and node.kind != tok.BREAK:
+ return node
+ exit_points = set(map(break_to_none, exit_points))
# Check if the switch had a default case
if not switch_has_default:
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mat...@us...> - 2008-09-01 14:04:12
|
Revision: 236
http://javascriptlint.svn.sourceforge.net/javascriptlint/?rev=236&view=rev
Author: matthiasmiller
Date: 2008-09-01 14:04:10 +0000 (Mon, 01 Sep 2008)
Log Message:
-----------
allow jsparse to locate possible comments before the script is parsed
Modified Paths:
--------------
trunk/pyjsl/jsparse.py
trunk/pyjsl/lint.py
Modified: trunk/pyjsl/jsparse.py
===================================================================
--- trunk/pyjsl/jsparse.py 2008-09-01 13:56:13 UTC (rev 235)
+++ trunk/pyjsl/jsparse.py 2008-09-01 14:04:10 UTC (rev 236)
@@ -145,7 +145,7 @@
return True
-def _parse_comments(script, node_positions, ignore_ranges):
+def findpossiblecomments(script, node_positions):
pos = 0
single_line_re = r"//[^\r\n]*"
multi_line_re = r"/\*(.*?)\*/"
@@ -169,31 +169,30 @@
opcode = opcode[5:].lower()
start_offset = match.start()
- end_offset = match.end()
+ end_offset = match.end()-1
- # Make sure it doesn't start in a string or regexp
- if not ignore_ranges.has(start_offset):
- start_pos = node_positions.from_offset(start_offset)
- end_pos = node_positions.from_offset(end_offset)
- kwargs = {
- 'type': 'COMMENT',
- 'atom': comment_text,
- 'opcode': opcode,
- '_start_line': start_pos.line,
- '_start_col': start_pos.col,
- '_end_line': end_pos.line,
- '_end_col': end_pos.col,
- 'parent': None,
- 'kids': [],
- 'node_index': None
- }
- comment_node = _Node()
- comment_node.__dict__.update(kwargs)
- comments.append(comment_node)
- pos = match.end()
- else:
- pos = match.start()+1
+ start_pos = node_positions.from_offset(start_offset)
+ end_pos = node_positions.from_offset(end_offset)
+ kwargs = {
+ 'type': 'COMMENT',
+ 'atom': comment_text,
+ 'opcode': opcode,
+ '_start_line': start_pos.line,
+ '_start_col': start_pos.col,
+ '_end_line': end_pos.line,
+ '_end_col': end_pos.col,
+ 'parent': None,
+ 'kids': [],
+ 'node_index': None
+ }
+ comment_node = _Node()
+ comment_node.__dict__.update(kwargs)
+ comments.append(comment_node)
+ # Start searching immediately after the start of the comment in case
+ # this one was within a string or a regexp.
+ pos = match.start()+1
+
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).
@@ -207,28 +206,37 @@
return pyspidermonkey.parse(script, _Node, _wrapped_callback,
startpos.line, startpos.col)
-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).
- """
- positions = NodePositions(script, startpos)
+def filtercomments(possible_comments, node_positions, root_node):
comment_ignore_ranges = NodeRanges()
def process(node):
if node.kind == tok.NUMBER:
- node.atom = positions.text(node.start_pos(), node.end_pos())
+ node.atom = node_positions.text(node.start_pos(), node.end_pos())
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()) - 1
+ start_offset = node_positions.to_offset(node.start_pos())
+ end_offset = node_positions.to_offset(node.end_pos()) - 1
comment_ignore_ranges.add(start_offset, end_offset)
for kid in node.kids:
if kid:
process(kid)
process(root_node)
- return _parse_comments(script, positions, comment_ignore_ranges)
+ comments = []
+ for comment in possible_comments:
+ start_offset = node_positions.to_offset(comment.start_pos())
+ end_offset = node_positions.to_offset(comment.end_pos())
+ if comment_ignore_ranges.has(start_offset):
+ continue
+ comment_ignore_ranges.add(start_offset, end_offset)
+ comments.append(comment)
+ return comments
+def findcomments(script, root_node, start_pos=None):
+ node_positions = NodePositions(script, start_pos)
+ possible_comments = findpossiblecomments(script, node_positions)
+ return filtercomments(possible_comments, node_positions, root_node)
+
def is_compilable_unit(script):
return pyspidermonkey.is_compilable_unit(script)
@@ -258,7 +266,7 @@
class TestComments(unittest.TestCase):
def _test(self, script, expected_comments):
root = parse(script, lambda line, col, msg: None)
- comments = parsecomments(script, root)
+ comments = findcomments(script, root)
encountered_comments = [node.atom for node in comments]
self.assertEquals(encountered_comments, list(expected_comments))
def testSimpleComments(self):
@@ -386,7 +394,7 @@
def testComments(self):
def testcomment(comment, startpos, expectedpos):
root = parse(comment, None, startpos)
- comment, = parsecomments(comment, root, startpos)
+ comment, = findcomments(comment, root, startpos)
self.assertEquals(comment.start_pos(), expectedpos)
for comment in ('/*comment*/', '//comment'):
testcomment(comment, None, NodePos(0,0))
Modified: trunk/pyjsl/lint.py
===================================================================
--- trunk/pyjsl/lint.py 2008-09-01 13:56:13 UTC (rev 235)
+++ trunk/pyjsl/lint.py 2008-09-01 14:04:10 UTC (rev 236)
@@ -288,6 +288,9 @@
fallthrus = []
passes = []
+ node_positions = jsparse.NodePositions(script, scriptpos)
+ possible_comments = jsparse.findpossiblecomments(script, node_positions)
+
root = jsparse.parse(script, parse_error, scriptpos)
if not root:
# Report errors and quit.
@@ -295,7 +298,7 @@
report_native(pos, msg)
return
- comments = jsparse.parsecomments(script, root, scriptpos)
+ comments = jsparse.filtercomments(possible_comments, node_positions, root)
start_ignore = None
for comment in comments:
cc = _parse_control_comment(comment)
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mat...@us...> - 2008-09-01 13:56:16
|
Revision: 235
http://javascriptlint.svn.sourceforge.net/javascriptlint/?rev=235&view=rev
Author: matthiasmiller
Date: 2008-09-01 13:56:13 +0000 (Mon, 01 Sep 2008)
Log Message:
-----------
move knowledge of script excerpts into NodePositions
Modified Paths:
--------------
trunk/pyjsl/jsparse.py
Modified: trunk/pyjsl/jsparse.py
===================================================================
--- trunk/pyjsl/jsparse.py 2008-08-28 16:24:36 UTC (rev 234)
+++ trunk/pyjsl/jsparse.py 2008-09-01 13:56:13 UTC (rev 235)
@@ -21,9 +21,10 @@
class NodePositions:
" Given a string, allows [x] lookups for NodePos line and column numbers."
- def __init__(self, text):
+ def __init__(self, text, start_pos=None):
# Find the length of each line and incrementally sum all of the lengths
# to determine the ending position of each line.
+ self._start_pos = start_pos
self._lines = text.splitlines(True)
lines = [0] + [len(x) for x in self._lines]
for x in range(1, len(lines)):
@@ -32,18 +33,34 @@
def from_offset(self, offset):
line = bisect.bisect(self._line_offsets, offset)-1
col = offset - self._line_offsets[line]
+ if self._start_pos:
+ if line == 0:
+ col += self._start_pos.col
+ line += self._start_pos.line
return NodePos(line, col)
def to_offset(self, pos):
+ pos = self._to_rel_pos(pos)
offset = self._line_offsets[pos.line] + pos.col
assert offset <= self._line_offsets[pos.line+1] # out-of-bounds col num
return offset
def text(self, start, end):
assert start <= end
+ start, end = self._to_rel_pos(start), self._to_rel_pos(end)
# Trim the ending first in case it's a single line.
lines = self._lines[start.line:end.line+1]
lines[-1] = lines[-1][:end.col+1]
lines[0] = lines[0][start.col:]
return ''.join(lines)
+ def _to_rel_pos(self, pos):
+ " converts a position to a position relative to self._start_pos "
+ if not self._start_pos:
+ return pos
+ line, col = pos.line, pos.col
+ line -= self._start_pos.line
+ if line == 0:
+ col -= self._start_pos.col
+ assert line >= 0 and col >= 0 # out-of-bounds node position
+ return NodePos(line, col)
class NodeRanges:
def __init__(self):
@@ -194,11 +211,7 @@
""" 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)
+ positions = NodePositions(script, startpos)
comment_ignore_ranges = NodeRanges()
def process(node):
@@ -290,6 +303,14 @@
self.assertEquals(pos.to_offset(NodePos(0, 2)), 2)
self.assertEquals(pos.to_offset(NodePos(1, 0)), 5)
self.assertEquals(pos.to_offset(NodePos(3, 1)), 11)
+ def testStartPos(self):
+ pos = NodePositions('abc\r\ndef\n\nghi', NodePos(3,4))
+ self.assertEquals(pos.to_offset(NodePos(3, 4)), 0)
+ self.assertEquals(pos.to_offset(NodePos(3, 5)), 1)
+ self.assertEquals(pos.from_offset(0), NodePos(3, 4))
+ self.assertEquals(pos.text(NodePos(3, 4), NodePos(3, 4)), 'a')
+ self.assertEquals(pos.text(NodePos(3, 4), NodePos(3, 6)), 'abc')
+ self.assertEquals(pos.text(NodePos(3, 6), NodePos(4, 2)), 'c\r\ndef')
class TestNodeRanges(unittest.TestCase):
def testAdd(self):
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mat...@us...> - 2008-08-28 16:24:40
|
Revision: 234
http://javascriptlint.svn.sourceforge.net/javascriptlint/?rev=234&view=rev
Author: matthiasmiller
Date: 2008-08-28 16:24:36 +0000 (Thu, 28 Aug 2008)
Log Message:
-----------
handle IE conditional comments
Modified Paths:
--------------
trunk/pyjsl/htmlparse.py
Modified: trunk/pyjsl/htmlparse.py
===================================================================
--- trunk/pyjsl/htmlparse.py 2008-08-28 14:27:08 UTC (rev 233)
+++ trunk/pyjsl/htmlparse.py 2008-08-28 16:24:36 UTC (rev 234)
@@ -41,6 +41,10 @@
self._node_positions = jsparse.NodePositions(self.rawdata + data)
HTMLParser.HTMLParser.feed(self, data)
+ def unknown_decl(self, data):
+ # Ignore unknown declarations instead of raising an exception.
+ pass
+
def getscripts(self):
return self._scripts
@@ -77,4 +81,9 @@
"",
"<!--\nvar s = '<script></script>';\n-->"
])
-
+ def testConditionalComments(self):
+ html = """
+<!--[if IE]>This is Internet Explorer.<![endif]-->
+<![if !IE]>This is not Internet Explorer<![endif]>
+"""
+ findscripts(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...> - 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 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 00:25:44
|
Revision: 230
http://javascriptlint.svn.sourceforge.net/javascriptlint/?rev=230&view=rev
Author: matthiasmiller
Date: 2008-08-28 00:25:42 +0000 (Thu, 28 Aug 2008)
Log Message:
-----------
improve pyjsl.lint.Scope's contract:
* Outer-level scopes will never be associated with a node.
* All inner-level scopes will always be associated with a node.
Modified Paths:
--------------
trunk/pyjsl/lint.py
Modified: trunk/pyjsl/lint.py
===================================================================
--- trunk/pyjsl/lint.py 2008-08-28 00:18:44 UTC (rev 229)
+++ trunk/pyjsl/lint.py 2008-08-28 00:25:42 UTC (rev 230)
@@ -72,16 +72,20 @@
return (comment, keyword, parms)
class Scope:
- def __init__(self, node):
- """ node may be None """
+ """ Outer-level scopes will never be associated with a node.
+ Inner-level scopes will always be associated with a node.
+ """
+ def __init__(self):
self._parent = None
self._kids = []
self._identifiers = {}
self._references = []
- self._node = node
+ self._node = None
def add_scope(self, node):
- self._kids.append(Scope(node))
+ assert not node is None
+ self._kids.append(Scope())
self._kids[-1]._parent = self
+ self._kids[-1]._node = node
return self._kids[-1]
def add_declaration(self, name, node):
self._identifiers[name] = node
@@ -157,22 +161,22 @@
child._find_unreferenced_and_undeclared(unreferenced, undeclared,
is_in_with_scope)
def find_scope(self, node):
- if not self._node:
- return None
-
for kid in self._kids:
scope = kid.find_scope(node)
if scope:
return scope
# Always add it to the outer scope.
- if not self._parent or \
- (node.start_pos() >= self._node.start_pos() and \
+ if not self._parent:
+ assert not self._node
+ return self
+
+ # Conditionally add it to an inner scope.
+ assert self._node
+ if (node.start_pos() >= self._node.start_pos() and \
node.end_pos() <= self._node.end_pos()):
return self
- return None
-
def lint_files(paths, lint_error, conf=conf.Conf()):
def lint_file(path):
def import_script(import_path):
@@ -258,7 +262,7 @@
# Cache empty results for this script.
assert not script_cache
script_cache['imports'] = set()
- script_cache['scope'] = Scope(None)
+ script_cache['scope'] = Scope()
# Report errors and quit.
for pos, msg in parse_errors:
@@ -321,7 +325,7 @@
assert not script_cache
imports = script_cache['imports'] = set()
- scope = script_cache['scope'] = Scope(root)
+ scope = script_cache['scope'] = Scope()
# Push the scope/variable checks.
visitation.make_visitors(visitors, [_get_scope_checks(scope, report)])
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:18:46
|
Revision: 229
http://javascriptlint.svn.sourceforge.net/javascriptlint/?rev=229&view=rev
Author: matthiasmiller
Date: 2008-08-28 00:18:44 +0000 (Thu, 28 Aug 2008)
Log Message:
-----------
pyjsl.lint.Scope's contract indicates that "node" may be None
Modified Paths:
--------------
trunk/pyjsl/lint.py
Modified: trunk/pyjsl/lint.py
===================================================================
--- trunk/pyjsl/lint.py 2008-08-28 00:14:15 UTC (rev 228)
+++ trunk/pyjsl/lint.py 2008-08-28 00:18:44 UTC (rev 229)
@@ -128,7 +128,8 @@
(scope, name, node)
]
"""
- is_in_with_scope = is_in_with_scope or self._node.kind == tok.WITH
+ if self._node and self._node.kind == tok.WITH:
+ is_in_with_scope = True
# Add all identifiers as unreferenced. Children scopes will remove
# them if they are referenced. Variables need to be keyed by name
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 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-27 16:11:36
|
Revision: 226
http://javascriptlint.svn.sourceforge.net/javascriptlint/?rev=226&view=rev
Author: matthiasmiller
Date: 2008-08-27 16:11:25 +0000 (Wed, 27 Aug 2008)
Log Message:
-----------
unreferenced_identifier: add another test case
Modified Paths:
--------------
trunk/tests/warnings/unreferenced_identifier.js
Modified: trunk/tests/warnings/unreferenced_identifier.js
===================================================================
--- trunk/tests/warnings/unreferenced_identifier.js 2008-08-27 02:30:20 UTC (rev 225)
+++ trunk/tests/warnings/unreferenced_identifier.js 2008-08-27 16:11:25 UTC (rev 226)
@@ -72,6 +72,10 @@
tmp = ref_dec--; /*warning:inc_dec_within_stmt*/
tmp = -tmp;
+ /* Test named functions as references. */
+ var fn = function ref_func() { return 42; }; /*warning:unreferenced_identifier*/
+ fn();
+
/* 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 02:30:23
|
Revision: 225
http://javascriptlint.svn.sourceforge.net/javascriptlint/?rev=225&view=rev
Author: matthiasmiller
Date: 2008-08-27 02:30:20 +0000 (Wed, 27 Aug 2008)
Log Message:
-----------
tweak output of the --dump parameter
Modified Paths:
--------------
trunk/pyjsl/jsparse.py
Modified: trunk/pyjsl/jsparse.py
===================================================================
--- trunk/pyjsl/jsparse.py 2008-08-27 01:59:38 UTC (rev 224)
+++ trunk/pyjsl/jsparse.py 2008-08-27 02:30:20 UTC (rev 225)
@@ -12,6 +12,10 @@
[getattr(tok, prop) for prop in dir(tok)],
['tok.%s' % prop for prop in dir(tok)]
))
+_op_names = dict(zip(
+ [getattr(op, prop) for prop in dir(op)],
+ ['op.%s' % prop for prop in dir(op)]
+))
NodePos = pyspidermonkey.NodePos
@@ -204,11 +208,19 @@
return pyspidermonkey.is_compilable_unit(script)
def _dump_node(node, depth=0):
- print '. '*depth,
if node is None:
- print '(none)'
+ print ' '*depth,
+ print '(None)'
+ print
else:
- print '%s\t%s, %s' % (_tok_names[node.kind], node.start_pos(), node.end_pos())
+ print ' '*depth,
+ print '%s, %s' % (_tok_names[node.kind], _op_names[node.opcode])
+ print ' '*depth,
+ print '%s - %s' % (node.start_pos(), node.end_pos())
+ if hasattr(node, 'atom'):
+ print ' '*depth,
+ print 'atom: %s' % node.atom
+ print
for node in node.kids:
_dump_node(node, depth+1)
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:59:41
|
Revision: 224
http://javascriptlint.svn.sourceforge.net/javascriptlint/?rev=224&view=rev
Author: matthiasmiller
Date: 2008-08-27 01:59:38 +0000 (Wed, 27 Aug 2008)
Log Message:
-----------
fix for reading blank files
Modified Paths:
--------------
trunk/pyjsl/util.py
Modified: trunk/pyjsl/util.py
===================================================================
--- trunk/pyjsl/util.py 2008-08-27 01:58:41 UTC (rev 223)
+++ trunk/pyjsl/util.py 2008-08-27 01:59:38 UTC (rev 224)
@@ -12,7 +12,7 @@
def readfile(path):
file = codecs.open(path, 'r', 'utf-8')
contents = file.read()
- if contents[0] == unicode(codecs.BOM_UTF8, 'utf8'):
+ if contents and contents[0] == unicode(codecs.BOM_UTF8, 'utf8'):
contents = contents[1:]
return contents
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-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-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 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 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 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: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-24 00:39:23
|
Revision: 216
http://javascriptlint.svn.sourceforge.net/javascriptlint/?rev=216&view=rev
Author: matthiasmiller
Date: 2008-08-24 00:39:17 +0000 (Sun, 24 Aug 2008)
Log Message:
-----------
silence warning
Modified Paths:
--------------
trunk/tests/path_resolution/is_a_file_not_dir.js
Modified: trunk/tests/path_resolution/is_a_file_not_dir.js
===================================================================
--- trunk/tests/path_resolution/is_a_file_not_dir.js 2008-08-24 00:37:04 UTC (rev 215)
+++ trunk/tests/path_resolution/is_a_file_not_dir.js 2008-08-24 00:39:17 UTC (rev 216)
@@ -1,2 +1,2 @@
/*conf:+process file/ */
-/*conf_error:unable to resolve path: file/*/
+/*conf_error:unable to resolve path: file/*/ /*warning:nested_comment*/
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-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-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.
|