[javascriptlint-commit] SF.net SVN: javascriptlint:[227] trunk
Status: Beta
Brought to you by:
matthiasmiller
|
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.
|