[javascriptlint-commit] SF.net SVN: javascriptlint:[238] trunk
Status: Beta
Brought to you by:
matthiasmiller
|
From: <mat...@us...> - 2009-03-03 17:03:09
|
Revision: 238
http://javascriptlint.svn.sourceforge.net/javascriptlint/?rev=238&view=rev
Author: matthiasmiller
Date: 2009-03-03 17:02:59 +0000 (Tue, 03 Mar 2009)
Log Message:
-----------
missing_semicolon: implement the missing semicolon warning
This is not the most elegant solution, but it requires the least invasive changes to spidermonkey.
Modified Paths:
--------------
trunk/pyjsl/jsparse.py
trunk/pyjsl/lint.py
trunk/pyjsl/warnings.py
trunk/pyspidermonkey/pyspidermonkey.c
trunk/spidermonkey/src/jsparse.c
trunk/spidermonkey/src/jsparse.h
trunk/test.py
trunk/tests/control_comments/declare.js
trunk/tests/warnings/missing_semicolon.js
trunk/tests/warnings/unreferenced_identifier.js
Added Paths:
-----------
trunk/tests/warnings/missing_semicolon_for_lambda.js
Removed Paths:
-------------
trunk/tests/conf/lambda_assign_requires_semicolon.js
Modified: trunk/pyjsl/jsparse.py
===================================================================
--- trunk/pyjsl/jsparse.py 2008-09-01 15:57:37 UTC (rev 237)
+++ trunk/pyjsl/jsparse.py 2009-03-03 17:02:59 UTC (rev 238)
@@ -253,6 +253,9 @@
if hasattr(node, 'atom'):
print ' '*depth,
print 'atom: %s' % node.atom
+ if node.no_semi:
+ print ' '*depth,
+ print '(no semicolon)'
print
for node in node.kids:
_dump_node(node, depth+1)
Modified: trunk/pyjsl/lint.py
===================================================================
--- trunk/pyjsl/lint.py 2008-09-01 15:57:37 UTC (rev 237)
+++ trunk/pyjsl/lint.py 2009-03-03 17:02:59 UTC (rev 238)
@@ -376,7 +376,13 @@
def _lint_script_parts(script_parts, script_cache, lint_error, conf, import_callback):
def report_lint(node, errname):
- _report(node.start_pos(), errname, True)
+ # TODO: This is ugly hardcoding to improve the error positioning of
+ # "missing_semicolon" errors.
+ if errname == 'missing_semicolon' or errname == 'missing_semicolon_for_lambda':
+ pos = node.end_pos()
+ else:
+ pos = node.start_pos()
+ _report(pos, errname, True)
def report_native(pos, errname):
_report(pos, errname, False)
Modified: trunk/pyjsl/warnings.py
===================================================================
--- trunk/pyjsl/warnings.py 2008-09-01 15:57:37 UTC (rev 237)
+++ trunk/pyjsl/warnings.py 2009-03-03 17:02:59 UTC (rev 238)
@@ -22,6 +22,24 @@
import visitation
from pyspidermonkey import tok, op
+_ALL_TOKENS = tuple(filter(lambda x: x != tok.EOF, tok.__dict__.values()))
+
+def _get_assigned_lambda(node):
+ """ Given a node "x = function() {}", returns "function() {}".
+ """
+ value = None
+ if node.kind == tok.SEMI:
+ assign_node, = node.kids
+ if assign_node and assign_node.kind == tok.ASSIGN:
+ ignored, value = assign_node.kids
+ elif node.kind == tok.VAR:
+ variables = node.kids
+ if variables:
+ value, = variables[-1].kids
+
+ if value and value.kind == tok.FUNCTION and value.opcode == op.ANONFUNOBJ:
+ return value
+
# TODO: document inspect, node:opcode, etc
warnings = {
@@ -63,6 +81,7 @@
'var_hides_arg': 'variable {0} hides argument',
'duplicate_formal': 'TODO',
'missing_semicolon': 'missing semicolon',
+ 'missing_semicolon_for_lambda': 'missing semicolon for lambda assignment',
'ambiguous_newline': 'unexpected end of line; it is ambiguous whether these lines are part of the same statement',
'missing_option_explicit': 'the "option explicit" control comment is missing',
'partial_option_explicit': 'the "option explicit" control comment, if used, must be in the first script tag',
@@ -538,10 +557,21 @@
def duplicate_formal(node):
pass
-@lookfor()
+@lookfor(*_ALL_TOKENS)
def missing_semicolon(node):
- pass
+ if node.no_semi:
+ if not _get_assigned_lambda(node):
+ raise LintWarning, node
+@lookfor(*_ALL_TOKENS)
+def missing_semicolon_for_lambda(node):
+ if node.no_semi:
+ # spidermonkey sometimes returns incorrect positions for var
+ # statements, so use the position of the lambda instead.
+ lambda_ = _get_assigned_lambda(node)
+ if lambda_:
+ raise LintWarning, lambda_
+
@lookfor()
def ambiguous_newline(node):
pass
Modified: trunk/pyspidermonkey/pyspidermonkey.c
===================================================================
--- trunk/pyspidermonkey/pyspidermonkey.c 2008-09-01 15:57:37 UTC (rev 237)
+++ trunk/pyspidermonkey/pyspidermonkey.c 2009-03-03 17:02:59 UTC (rev 238)
@@ -303,6 +303,9 @@
goto fail;
}
+ if (PyObject_SetAttrString(pynode, "no_semi", PyBool_FromLong(jsnode->pn_no_semi)) == -1)
+ goto fail;
+
switch (jsnode->pn_arity) {
case PN_FUNC:
kids = PyTuple_New(1);
Modified: trunk/spidermonkey/src/jsparse.c
===================================================================
--- trunk/spidermonkey/src/jsparse.c 2008-09-01 15:57:37 UTC (rev 237)
+++ trunk/spidermonkey/src/jsparse.c 2009-03-03 17:02:59 UTC (rev 238)
@@ -248,6 +248,7 @@
pn->pn_next = NULL;
pn->pn_ts = ts;
pn->pn_source = NULL;
+ pn->pn_no_semi = JS_FALSE;
return pn;
}
@@ -324,6 +325,7 @@
pn->pn_next = NULL;
pn->pn_ts = NULL;
pn->pn_source = NULL;
+ pn->pn_no_semi = JS_FALSE;
return pn;
}
@@ -2738,7 +2740,8 @@
* insertion after do-while. See the testcase and discussion in
* http://bugzilla.mozilla.org/show_bug.cgi?id=238945.
*/
- (void) js_MatchToken(cx, ts, TOK_SEMI);
+ if (!js_MatchToken(cx, ts, TOK_SEMI))
+ pn->pn_no_semi = JS_TRUE;
return pn;
}
break;
@@ -3476,6 +3479,8 @@
return NULL;
pn->pn_type = TOK_SEMI;
pn->pn_kid = NULL;
+ if (tt == TOK_EOL)
+ pn->pn_no_semi = JS_TRUE;
return pn;
#if JS_HAS_DEBUGGER_KEYWORD
@@ -3588,7 +3593,8 @@
}
}
- (void) js_MatchToken(cx, ts, TOK_SEMI);
+ if (!js_MatchToken(cx, ts, TOK_SEMI))
+ pn->pn_no_semi = JS_TRUE;
return pn;
}
@@ -4311,6 +4317,7 @@
pn2->pn_next = NULL;
pn2->pn_ts = ts;
pn2->pn_source = NULL;
+ pn2->pn_no_semi = JS_FALSE;
pn = pn2;
}
}
Modified: trunk/spidermonkey/src/jsparse.h
===================================================================
--- trunk/spidermonkey/src/jsparse.h 2008-09-01 15:57:37 UTC (rev 237)
+++ trunk/spidermonkey/src/jsparse.h 2009-03-03 17:02:59 UTC (rev 238)
@@ -317,6 +317,7 @@
JSParseNode *pn_next; /* to align dval and pn_u on RISCs */
JSTokenStream *pn_ts; /* token stream for error reports */
JSAtom *pn_source; /* saved source for decompilation */
+ JSBool pn_no_semi; /* missing semicolon */
};
#define pn_funAtom pn_u.func.funAtom
Modified: trunk/test.py
===================================================================
--- trunk/test.py 2008-09-01 15:57:37 UTC (rev 237)
+++ trunk/test.py 2009-03-03 17:02:59 UTC (rev 238)
@@ -32,7 +32,6 @@
for warning in regexp.findall(lines[i]):
# TODO: implement these
unimpl_warnings = ('ambiguous_newline', 'dup_option_explicit',
- 'missing_semicolon'
)
if not warning in unimpl_warnings:
warnings.append((i, warning))
Deleted: trunk/tests/conf/lambda_assign_requires_semicolon.js
===================================================================
--- trunk/tests/conf/lambda_assign_requires_semicolon.js 2008-09-01 15:57:37 UTC (rev 237)
+++ trunk/tests/conf/lambda_assign_requires_semicolon.js 2009-03-03 17:02:59 UTC (rev 238)
@@ -1,43 +0,0 @@
-/*conf:-lambda_assign_requires_semicolon*/
-
-
-/* Test with a simple variable. */
-var x = function() {
- return {};
-}
-x();
-
-var a, b = function() { }, c
-b(); /*warning:missing_semicolon*/
-var d, e = function() { }
-e();
-
-var y;
-y = function() {
- return [];
-}
-y();
-
-global = function() {
- return null;
-}
-global();
-
-function Foo()
-{
- this.bar = 10;
-
- /* Test an assignment to a member. */
- this.setBar = function(bar) {
- this.bar = bar;
- }
-
- this.setBar(this.bar * 2);
-}
-
-/* Test an assignment to a prototype. */
-Foo.prototype.getBar = function() {
- return this.bar;
-}
-
-var foo = new Foo();
Modified: trunk/tests/control_comments/declare.js
===================================================================
--- trunk/tests/control_comments/declare.js 2008-09-01 15:57:37 UTC (rev 237)
+++ trunk/tests/control_comments/declare.js 2009-03-03 17:02:59 UTC (rev 238)
@@ -9,8 +9,8 @@
/*jsl:declare document*//*warning:redeclared_var*/
}
-var i = 10
-/*jsl:declare sample*//*warning:missing_semicolon*/
+var i = 10 /*warning:missing_semicolon*/
+/*jsl:declare sample*/
/* declare was scoped */
window.alert('JavaScript Lint');/*warning:undeclared_identifier*/
Modified: trunk/tests/warnings/missing_semicolon.js
===================================================================
--- trunk/tests/warnings/missing_semicolon.js 2008-09-01 15:57:37 UTC (rev 237)
+++ trunk/tests/warnings/missing_semicolon.js 2009-03-03 17:02:59 UTC (rev 238)
@@ -1,19 +1,23 @@
/*jsl:option explicit*/
+
function missing_semicolon() {
/* missing semicolon after return */
function MissingSemicolonOnReturnStatement() {
- return 0
- } /*warning:missing_semicolon*/
+ return 0 /*warning:missing_semicolon*/
+ }
+ function MissingSemicolonOnReturnStatement2() { return 0 } /*warning:missing_semicolon*/
- /* missing semicolon after return */
/* missing semicolon after lambda */
function x() {
- this.y = function() { return 0 } /*warning:missing_semicolon*/
- } /*warning:missing_semicolon*/
+ this.y = function() { return 0; } /*warning:missing_semicolon_for_lambda*/
+ }
- /* missing semicolon after return */
/* missing semicolon after lambda */
x.prototype.z = function() {
- return 1
- } /*warning:missing_semicolon*/
-} /*warning:missing_semicolon*/
+ return 1;
+ } /*warning:missing_semicolon_for_lambda*/
+
+ do x++;
+ while (x < 10) /*warning:missing_semicolon*/
+}
+
Copied: trunk/tests/warnings/missing_semicolon_for_lambda.js (from rev 237, trunk/tests/conf/lambda_assign_requires_semicolon.js)
===================================================================
--- trunk/tests/warnings/missing_semicolon_for_lambda.js (rev 0)
+++ trunk/tests/warnings/missing_semicolon_for_lambda.js 2009-03-03 17:02:59 UTC (rev 238)
@@ -0,0 +1,43 @@
+/*jsl:option explicit*/
+/*jsl:declare global*/
+
+/* Test with a simple variable. */
+var x = function() {
+ return {};
+} /*warning:missing_semicolon_for_lambda*/
+x();
+
+var a, b = function() { }, c /*warning:missing_semicolon*/
+b();
+var d, e = function() { } /*warning:missing_semicolon_for_lambda*/
+e();
+
+var y;
+y = function() {
+ return [];
+} /*warning:missing_semicolon_for_lambda*/
+y();
+
+global = function() {
+ return null;
+} /*warning:missing_semicolon_for_lambda*/
+global();
+
+function Foo()
+{
+ this.bar = 10;
+
+ /* Test an assignment to a member. */
+ this.setBar = function(bar) {
+ this.bar = bar;
+ } /*warning:missing_semicolon_for_lambda*/
+
+ this.setBar(this.bar * 2);
+}
+
+/* Test an assignment to a prototype. */
+Foo.prototype.getBar = function() {
+ return this.bar;
+} /*warning:missing_semicolon_for_lambda*/
+
+var foo = new Foo();
Modified: trunk/tests/warnings/unreferenced_identifier.js
===================================================================
--- trunk/tests/warnings/unreferenced_identifier.js 2008-09-01 15:57:37 UTC (rev 237)
+++ trunk/tests/warnings/unreferenced_identifier.js 2009-03-03 17:02:59 UTC (rev 238)
@@ -15,7 +15,7 @@
/* Test an unreferenced parameter. */
var z = new function(unreferenced_parm) { /*warning:unreferenced_identifier*/
- }
+ };
z.prop = 42;
/* Test an unreferenced variable. */
@@ -80,7 +80,7 @@
function get_callback(parm) {
return function() {
return parm;
- }
+ };
}
return get_callback(42);
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|