Thread: [javascriptlint-commit] SF.net SVN: javascriptlint:[301] trunk (Page 3)
Status: Beta
Brought to you by:
matthiasmiller
|
From: <mat...@us...> - 2010-10-03 20:18:17
|
Revision: 301
http://javascriptlint.svn.sourceforge.net/javascriptlint/?rev=301&view=rev
Author: matthiasmiller
Date: 2010-10-03 20:18:10 +0000 (Sun, 03 Oct 2010)
Log Message:
-----------
Add support for content types and differing JavaScript versions.
Modified Paths:
--------------
trunk/javascriptlint/conf.py
trunk/javascriptlint/jsparse.py
trunk/javascriptlint/lint.py
trunk/javascriptlint/pyspidermonkey/pyspidermonkey.c
trunk/javascriptlint/util.py
trunk/javascriptlint/warnings.py
Added Paths:
-----------
trunk/tests/control_comments/conf-version-2.js
trunk/tests/control_comments/conf-version.js
trunk/tests/html/e4x.html
trunk/tests/html/unsupported_version.html
Modified: trunk/javascriptlint/conf.py
===================================================================
--- trunk/javascriptlint/conf.py 2010-04-23 21:09:57 UTC (rev 300)
+++ trunk/javascriptlint/conf.py 2010-10-03 20:18:10 UTC (rev 301)
@@ -2,6 +2,7 @@
import os
import unittest
+import util
import warnings
def _getwarningsconf():
@@ -80,6 +81,11 @@
#+define document
+### JavaScript Version
+# To change the default JavaScript version:
+#+default-type text/javascript;version=1.5
+#+default-type text/javascript;e4x=1
+
### Files
# Specify which files to lint
# Use "+recurse" to enable recursion (disabled by default).
@@ -144,6 +150,17 @@
parm = os.path.join(dir, parm)
self.value.append((self._recurse.value, parm))
+class JSVersionSetting(Setting):
+ wants_parm = True
+ value = util.JSVersion.default()
+ def load(self, enabled, parm):
+ if not enabled:
+ raise ConfError, 'Expected +.'
+
+ self.value = util.JSVersion.fromtype(parm)
+ if not self.value:
+ raise ConfError, 'Invalid JavaScript version: %s' % parm
+
class Conf:
def __init__(self):
recurse = BooleanSetting(False)
@@ -157,6 +174,7 @@
'define': DeclareSetting(),
'context': BooleanSetting(True),
'process': ProcessSetting(recurse),
+ 'default-version': JSVersionSetting(),
# SpiderMonkey warnings
'no_return_value': BooleanSetting(True),
'equal_as_assign': BooleanSetting(True),
Modified: trunk/javascriptlint/jsparse.py
===================================================================
--- trunk/javascriptlint/jsparse.py 2010-04-23 21:09:57 UTC (rev 300)
+++ trunk/javascriptlint/jsparse.py 2010-10-03 20:18:10 UTC (rev 301)
@@ -7,6 +7,7 @@
import spidermonkey
from spidermonkey import tok, op
+from util import JSVersion
_tok_names = dict(zip(
[getattr(tok, prop) for prop in dir(tok)],
@@ -145,6 +146,11 @@
return True
+def isvalidversion(jsversion):
+ if jsversion is None:
+ return True
+ return spidermonkey.is_valid_version(jsversion.version)
+
def findpossiblecomments(script, node_positions):
pos = 0
single_line_re = r"//[^\r\n]*"
@@ -193,7 +199,7 @@
# this one was within a string or a regexp.
pos = match.start()+1
-def parse(script, error_callback, startpos=None):
+def parse(script, jsversion, error_callback, startpos=None):
""" All node positions will be relative to startpos. This allows scripts
to be embedded in a file (for example, HTML).
"""
@@ -203,7 +209,10 @@
error_callback(line, col, msg)
startpos = startpos or NodePos(0,0)
- return spidermonkey.parse(script, _Node, _wrapped_callback,
+ jsversion = jsversion or JSVersion.default()
+ assert isvalidversion(jsversion)
+ return spidermonkey.parse(script, jsversion.version, jsversion.e4x,
+ _Node, _wrapped_callback,
startpos.line, startpos.col)
def filtercomments(possible_comments, node_positions, root_node):
@@ -237,8 +246,10 @@
possible_comments = findpossiblecomments(script, node_positions)
return filtercomments(possible_comments, node_positions, root_node)
-def is_compilable_unit(script):
- return spidermonkey.is_compilable_unit(script)
+def is_compilable_unit(script, jsversion):
+ jsversion = jsversion or JSVersion.default()
+ assert isvalidversion(jsversion)
+ return spidermonkey.is_compilable_unit(script, jsversion.version, jsversion.e4x)
def _dump_node(node, depth=0):
if node is None:
@@ -263,12 +274,12 @@
def dump_tree(script):
def error_callback(line, col, msg):
print '(%i, %i): %s', (line, col, msg)
- node = parse(script, error_callback)
+ node = parse(script, None, error_callback)
_dump_node(node)
class TestComments(unittest.TestCase):
def _test(self, script, expected_comments):
- root = parse(script, lambda line, col, msg: None)
+ root = parse(script, None, lambda line, col, msg: None)
comments = findcomments(script, root)
encountered_comments = [node.atom for node in comments]
self.assertEquals(encountered_comments, list(expected_comments))
@@ -365,10 +376,11 @@
('re = /.*', False),
('{ // missing curly', False)
)
- for text, result in tests:
- self.assertEquals(is_compilable_unit(text), result)
+ for text, expected in tests:
+ encountered = is_compilable_unit(text, JSVersion.default())
+ self.assertEquals(encountered, expected)
# NOTE: This seems like a bug.
- self.assert_(is_compilable_unit("/* test"))
+ self.assert_(is_compilable_unit("/* test", JSVersion.default()))
class TestLineOffset(unittest.TestCase):
def testErrorPos(self):
@@ -376,7 +388,7 @@
errors = []
def onerror(line, col, msg):
errors.append((line, col, msg))
- parse(script, onerror, startpos)
+ parse(script, None, onerror, startpos)
self.assertEquals(len(errors), 1)
return errors[0]
self.assertEquals(geterror(' ?', None), (0, 1, 'syntax_error'))
@@ -385,7 +397,7 @@
self.assertEquals(geterror('\n ?', NodePos(1,1)), (2, 1, 'syntax_error'))
def testNodePos(self):
def getnodepos(script, startpos):
- root = parse(script, None, startpos)
+ root = parse(script, None, None, startpos)
self.assertEquals(root.kind, tok.LC)
var, = root.kids
self.assertEquals(var.kind, tok.VAR)
@@ -398,7 +410,7 @@
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)
+ root = parse(comment, None, None, startpos)
comment, = findcomments(comment, root, startpos)
self.assertEquals(comment.start_pos(), expectedpos)
for comment in ('/*comment*/', '//comment'):
Modified: trunk/javascriptlint/lint.py
===================================================================
--- trunk/javascriptlint/lint.py 2010-04-23 21:09:57 UTC (rev 300)
+++ trunk/javascriptlint/lint.py 2010-10-03 20:18:10 UTC (rev 301)
@@ -63,6 +63,7 @@
'pass': (False),
'declare': (True),
'unused': (True),
+ 'content-type': (True),
}
if control_comment.lower() in control_comments:
keyword = control_comment.lower()
@@ -240,19 +241,21 @@
if global_:
return global_
-def _findhtmlscripts(contents):
+def _findhtmlscripts(contents, default_version):
starttag = None
nodepos = jsparse.NodePositions(contents)
for tag in htmlparse.findscripttags(contents):
if tag['type'] == 'start':
# Ignore nested start tags.
if not starttag:
- starttag = tag
+ jsversion = util.JSVersion.fromattr(tag['attr'], default_version)
+ starttag = dict(tag, jsversion=jsversion)
src = tag['attr'].get('src')
if src:
yield {
'type': 'external',
- 'src': src
+ 'jsversion': jsversion,
+ 'src': src,
}
elif tag['type'] == 'end':
if not starttag:
@@ -268,25 +271,27 @@
endoffset = nodepos.to_offset(endpos)
script = contents[startoffset:endoffset]
- if jsparse.is_compilable_unit(script):
- starttag = None
+ if not jsparse.isvalidversion(starttag['jsversion']) or \
+ jsparse.is_compilable_unit(script, starttag['jsversion']):
if script.strip():
yield {
'type': 'inline',
+ 'jsversion': starttag['jsversion'],
'pos': startpos,
'contents': script,
}
+ starttag = None
else:
assert False, 'Invalid internal tag type %s' % tag['type']
def lint_files(paths, lint_error, conf=conf.Conf(), printpaths=True):
- def lint_file(path, kind):
- def import_script(import_path):
+ def lint_file(path, kind, jsversion):
+ def import_script(import_path, jsversion):
# The user can specify paths using backslashes (such as when
# linting Windows scripts on a posix environment.
import_path = import_path.replace('\\', os.sep)
import_path = os.path.join(os.path.dirname(path), import_path)
- return lint_file(import_path, 'js')
+ return lint_file(import_path, 'js', jsversion)
def _lint_error(*args):
return lint_error(normpath, *args)
@@ -300,14 +305,20 @@
script_parts = []
if kind == 'js':
- script_parts.append((None, contents))
+ script_parts.append((None, jsversion or conf['default-version'], contents))
elif kind == 'html':
- for script in _findhtmlscripts(contents):
+ assert jsversion is None
+ for script in _findhtmlscripts(contents, conf['default-version']):
+ # TODO: Warn about foreign languages.
+ if not script['jsversion']:
+ continue
+
if script['type'] == 'external':
- other = import_script(script['src'])
+ other = import_script(script['src'], script['jsversion'])
lint_cache[normpath].importscript(other)
elif script['type'] == 'inline':
- script_parts.append((script['pos'], script['contents']))
+ script_parts.append((script['pos'], script['jsversion'],
+ script['contents']))
else:
assert False, 'Invalid internal script type %s' % \
script['type']
@@ -321,12 +332,12 @@
for path in paths:
ext = os.path.splitext(path)[1]
if ext.lower() in ['.htm', '.html']:
- lint_file(path, 'html')
+ lint_file(path, 'html', None)
else:
- lint_file(path, 'js')
+ lint_file(path, 'js', None)
-def _lint_script_part(scriptpos, script, script_cache, conf, ignores,
- report_native, report_lint, import_callback):
+def _lint_script_part(scriptpos, jsversion, 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'):
@@ -375,7 +386,28 @@
node_positions = jsparse.NodePositions(script, scriptpos)
possible_comments = jsparse.findpossiblecomments(script, node_positions)
- root = jsparse.parse(script, parse_error, scriptpos)
+ # Check control comments for the correct version. It may be this comment
+ # isn't a valid comment (for example, it might be inside a string literal)
+ # After parsing, validate that it's legitimate.
+ jsversionnode = None
+ for comment in possible_comments:
+ cc = _parse_control_comment(comment)
+ if cc:
+ node, keyword, parms = cc
+ if keyword == 'content-type':
+ ccversion = util.JSVersion.fromtype(parms)
+ if ccversion:
+ jsversion = ccversion
+ jsversionnode = node
+ else:
+ report(node, 'unsupported_version', version=parms)
+
+ if not jsparse.isvalidversion(jsversion):
+ report_lint(jsversionnode, 'unsupported_version', scriptpos,
+ version=jsversion.version)
+ return
+
+ root = jsparse.parse(script, jsversion, parse_error, scriptpos)
if not root:
# Report errors and quit.
for pos, msg in parse_errors:
@@ -383,6 +415,11 @@
return
comments = jsparse.filtercomments(possible_comments, node_positions, root)
+
+ if jsversionnode is not None and jsversionnode not in comments:
+ # TODO
+ report(jsversionnode, 'incorrect_version')
+
start_ignore = None
for comment in comments:
cc = _parse_control_comment(comment)
@@ -461,7 +498,7 @@
# Process imports by copying global declarations into the universal scope.
for path in import_paths:
- script_cache.importscript(import_callback(path))
+ script_cache.importscript(import_callback(path, jsversion))
for name, node in declares:
declare_scope = script_cache.scope.find_scope(node)
@@ -494,9 +531,9 @@
return lint_error(pos.line, pos.col, errname, errdesc)
- for scriptpos, script in script_parts:
+ for scriptpos, jsversion, script in script_parts:
ignores = []
- _lint_script_part(scriptpos, script, script_cache, conf, ignores,
+ _lint_script_part(scriptpos, jsversion, script, script_cache, conf, ignores,
report_native, report_lint, import_callback)
scope = script_cache.scope
@@ -620,8 +657,55 @@
</html>
"""
scripts = [(x.get('src'), x.get('contents'))
- for x in _findhtmlscripts(html)]
+ for x in _findhtmlscripts(html, util.JSVersion.default())]
self.assertEquals(scripts, [
('test.js', None),
(None, "<!--\nvar s = '<script></script>';\n-->")
])
+ def testJSVersion(self):
+ def parsetag(starttag, default_version=None):
+ script, = _findhtmlscripts(starttag + '/**/</script>', \
+ default_version)
+ return script
+
+ script = parsetag('<script>')
+ self.assertEquals(script['jsversion'], None)
+
+ script = parsetag('<script language="vbscript">')
+ self.assertEquals(script['jsversion'], None)
+
+ script = parsetag('<script type="text/javascript">')
+ self.assertEquals(script['jsversion'], util.JSVersion.default())
+
+ script = parsetag('<SCRIPT TYPE="TEXT/JAVASCRIPT">')
+ self.assertEquals(script['jsversion'], util.JSVersion.default())
+
+ script = parsetag('<script type="text/javascript; version = 1.6 ">')
+ self.assertEquals(script['jsversion'], util.JSVersion('1.6', False))
+
+ script = parsetag('<script type="text/javascript; version = 1.6 ">')
+ self.assertEquals(script['jsversion'], util.JSVersion('1.6', False))
+
+ script = parsetag('<SCRIPT TYPE="TEXT/JAVASCRIPT; e4x = 1 ">')
+ self.assertEquals(script['jsversion'], util.JSVersion('default', True))
+
+ script = parsetag('<script type="" language="livescript">')
+ self.assertEquals(script['jsversion'], util.JSVersion.default())
+
+ script = parsetag('<script type="" language="MOCHA">')
+ self.assertEquals(script['jsversion'], util.JSVersion.default())
+
+ script = parsetag('<script type="" language="JavaScript1.2">')
+ self.assertEquals(script['jsversion'], util.JSVersion('1.2', False))
+
+ script = parsetag('<script type="text/javascript;version=1.2" language="javascript1.4">')
+ self.assertEquals(script['jsversion'], util.JSVersion('1.2', False))
+
+ # Test setting the default version.
+ script = parsetag('<script>', util.JSVersion('1.2', False))
+ self.assertEquals(script['jsversion'], util.JSVersion('1.2', False))
+
+ script = parsetag('<script type="" language="mocha">',
+ util.JSVersion('1.2', False))
+ self.assertEquals(script['jsversion'], util.JSVersion.default())
+
Modified: trunk/javascriptlint/pyspidermonkey/pyspidermonkey.c
===================================================================
--- trunk/javascriptlint/pyspidermonkey/pyspidermonkey.c 2010-04-23 21:09:57 UTC (rev 300)
+++ trunk/javascriptlint/pyspidermonkey/pyspidermonkey.c 2010-10-03 20:18:10 UTC (rev 301)
@@ -70,6 +70,9 @@
static PyObject*
is_compilable_unit(PyObject *self, PyObject *args);
+static PyObject*
+is_valid_version(PyObject *self, PyObject *args);
+
static PyMethodDef module_methods[] = {
{"parse", module_parse, METH_VARARGS,
"Parses \"script\" and returns a tree of \"node_class\"."},
@@ -77,6 +80,9 @@
{"is_compilable_unit", is_compilable_unit, METH_VARARGS,
"Returns True if \"script\" is a compilable unit."},
+ {"is_valid_version", is_valid_version, METH_VARARGS,
+ "Returns True if \"strversion\" is a valid version."},
+
{NULL, NULL, 0, NULL} /* Sentinel */
};
@@ -398,13 +404,22 @@
/* Returns NULL on success. Otherwise, it returns an error.
* If the error is blank, an exception will be set.
*/
-static const char* create_jscontext(void* ctx_data,
+static const char* create_jscontext(const char* strversion, PyObject* is_e4x,
+ void* ctx_data,
JSRuntime** runtime, JSContext** context,
JSObject** global)
{
+ JSVersion jsversion;
+
+ jsversion = JS_StringToVersion(strversion);
+ if (jsversion == JSVERSION_UNKNOWN) {
+ PyErr_SetString(PyExc_ValueError, "\"version\" is invalid");
+ return "";
+ }
+
*runtime = JS_NewRuntime(8L * 1024L * 1024L);
if (*runtime == NULL)
- return"cannot create runtime";
+ return "cannot create runtime";
*context = JS_NewContext(*runtime, 8192);
if (*context == NULL)
@@ -413,6 +428,11 @@
JS_SetErrorReporter(*context, error_reporter);
JS_SetContextPrivate(*context, ctx_data);
JS_ToggleOptions(*context, JSOPTION_STRICT);
+ if (is_e4x == Py_True)
+ JS_ToggleOptions(*context, JSOPTION_XML);
+ else if (is_e4x != Py_False)
+ return "e4x is not a boolean";
+ JS_SetVersion(*context, jsversion);
*global = JS_NewObject(*context, NULL, NULL, NULL);
if (*global == NULL)
@@ -430,6 +450,8 @@
struct {
char* scriptbuf;
int scriptbuflen;
+ const char* jsversion;
+ PyObject* is_e4x;
PyObject* pynode;
JSRuntime* runtime;
@@ -446,8 +468,9 @@
error = "encountered an unknown error";
/* validate arguments */
- if (!PyArg_ParseTuple(args, "es#OOll", "utf16", &m.scriptbuf,
- &m.scriptbuflen, &m.ctx_data.node_class, &m.ctx_data.error_callback,
+ if (!PyArg_ParseTuple(args, "es#sO!OOll", "utf16", &m.scriptbuf,
+ &m.scriptbuflen, &m.jsversion, &PyBool_Type, &m.is_e4x,
+ &m.ctx_data.node_class, &m.ctx_data.error_callback,
&m.ctx_data.first_lineno, &m.ctx_data.first_index)) {
return NULL;
}
@@ -462,7 +485,8 @@
return NULL;
}
- error = create_jscontext(&m.ctx_data, &m.runtime, &m.context, &m.global);
+ error = create_jscontext(m.jsversion, m.is_e4x, &m.ctx_data,
+ &m.runtime, &m.context, &m.global);
if (error)
goto cleanup;
@@ -511,6 +535,8 @@
struct {
char* scriptbuf;
int scriptbuflen;
+ const char* jsversion;
+ PyObject* is_e4x;
JSRuntime* runtime;
JSContext* context;
JSObject* global;
@@ -521,10 +547,13 @@
memset(&m, 0, sizeof(m));
error = "encountered an unknown error";
- if (!PyArg_ParseTuple(args, "es#", "utf16", &m.scriptbuf, &m.scriptbuflen))
+ if (!PyArg_ParseTuple(args, "es#sO!", "utf16", &m.scriptbuf,
+ &m.scriptbuflen, &m.jsversion, &PyBool_Type, &m.is_e4x)) {
return NULL;
+ }
- error = create_jscontext(NULL, &m.runtime, &m.context, &m.global);
+ error = create_jscontext(m.jsversion, m.is_e4x, NULL,
+ &m.runtime, &m.context, &m.global);
if (error)
goto cleanup;
@@ -546,13 +575,22 @@
PyErr_SetString(PyExc_StandardError, error);
return NULL;
}
- if (m.is_compilable) {
- Py_INCREF(Py_True);
- return Py_True;
- }
- else {
- Py_INCREF(Py_False);
- return Py_False;
- }
+ if (m.is_compilable)
+ Py_RETURN_TRUE;
+ else
+ Py_RETURN_FALSE;
}
+static PyObject*
+is_valid_version(PyObject *self, PyObject *args) {
+ const char* strversion = NULL;
+
+ if (!PyArg_ParseTuple(args, "s", &strversion))
+ return NULL;
+
+ if (JS_StringToVersion(strversion) != JSVERSION_UNKNOWN)
+ Py_RETURN_TRUE;
+ else
+ Py_RETURN_FALSE;
+}
+
Modified: trunk/javascriptlint/util.py
===================================================================
--- trunk/javascriptlint/util.py 2010-04-23 21:09:57 UTC (rev 300)
+++ trunk/javascriptlint/util.py 2010-10-03 20:18:10 UTC (rev 301)
@@ -1,4 +1,5 @@
# vim: ts=4 sw=4 expandtab
+import cgi
import codecs
import os.path
import re
@@ -6,6 +7,57 @@
_identifier = re.compile('^[A-Za-z_$][A-Za-z0-9_$]*$')
+_contenttypes = (
+ 'text/javascript',
+ 'text/ecmascript',
+ 'application/javascript',
+ 'application/ecmascript',
+ 'application/x-javascript',
+)
+
+class JSVersion:
+ def __init__(self, jsversion, is_e4x):
+ self.version = jsversion
+ self.e4x = is_e4x
+
+ def __eq__(self, other):
+ return self.version == other.version and \
+ self.e4x == other.e4x
+
+ @classmethod
+ def default(klass):
+ return klass('default', False)
+
+ @classmethod
+ def fromattr(klass, attr, default_version=None):
+ if attr.get('type'):
+ return klass.fromtype(attr['type'])
+ if attr.get('language'):
+ return klass.fromlanguage(attr['language'])
+ return default_version
+
+ @classmethod
+ def fromtype(klass, type_):
+ typestr, typeparms = cgi.parse_header(type_)
+ if typestr.lower() in _contenttypes:
+ jsversion = typeparms.get('version', 'default')
+ is_e4x = typeparms.get('e4x') == '1'
+ return klass(jsversion, is_e4x)
+ return None
+
+ @classmethod
+ def fromlanguage(klass, language):
+ if language.lower() in ('javascript', 'livescript', 'mocha'):
+ return klass.default()
+
+ # Simplistic parsing of javascript/x.y
+ if language.lower().startswith('javascript'):
+ language = language[len('javascript'):]
+ if language.replace('.', '').isdigit():
+ return klass(language, False)
+
+ return None
+
def isidentifier(text):
return _identifier.match(text)
@@ -91,7 +143,6 @@
self.assertEquals(format_error('encode:__ERROR_MSGENC__', r'c:\my\file', 1, 2, 'name', r'a\b'),
r'a\\b')
-
if __name__ == '__main__':
unittest.main()
Modified: trunk/javascriptlint/warnings.py
===================================================================
--- trunk/javascriptlint/warnings.py 2010-04-23 21:09:57 UTC (rev 300)
+++ trunk/javascriptlint/warnings.py 2010-10-03 20:18:10 UTC (rev 301)
@@ -94,7 +94,9 @@
'invalid_pass': 'unexpected "pass" control comment',
'want_assign_or_call': 'expected an assignment or function call',
'no_return_value': 'function {name} does not always return a value',
- 'anon_no_return_value': 'anonymous function does not always return value'
+ 'anon_no_return_value': 'anonymous function does not always return value',
+ 'unsupported_version': 'JavaScript {version} is not supported',
+ 'incorrect_version': 'Expected /*jsl:content-type*/ control comment. The script was parsed with the wrong version.',
}
def format_error(errname, **errargs):
@@ -511,6 +513,8 @@
# NOTE: Don't handle comma-separated statements.
if child.kind in (tok.ASSIGN, tok.INC, tok.DEC, tok.DELETE, tok.COMMA):
return
+ if child.kind == tok.YIELD:
+ return
# Ignore function calls.
if child.kind == tok.LP and child.opcode == op.CALL:
return
Added: trunk/tests/control_comments/conf-version-2.js
===================================================================
--- trunk/tests/control_comments/conf-version-2.js (rev 0)
+++ trunk/tests/control_comments/conf-version-2.js 2010-10-03 20:18:10 UTC (rev 301)
@@ -0,0 +1,7 @@
+/*conf:+default-version text/javascript;version=1.7*/
+/*jsl:content-type text/javascript;version=1.6*/
+
+/* Make sure that the control comment overrides the config file. */
+function default_version() {
+ yield true; /*warning:semi_before_stmnt*/
+}
Added: trunk/tests/control_comments/conf-version.js
===================================================================
--- trunk/tests/control_comments/conf-version.js (rev 0)
+++ trunk/tests/control_comments/conf-version.js 2010-10-03 20:18:10 UTC (rev 301)
@@ -0,0 +1,4 @@
+/*conf:+default-version text/javascript;version=1.7*/
+function default_version() {
+ yield true;
+}
Added: trunk/tests/html/e4x.html
===================================================================
--- trunk/tests/html/e4x.html (rev 0)
+++ trunk/tests/html/e4x.html 2010-10-03 20:18:10 UTC (rev 301)
@@ -0,0 +1,28 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
+<html>
+<head>
+ <title>JavaScript Lint Test Page</title>
+ <!-- If e4x is disabled, HTML commments are treated as
+ comment-till-end-of-line. -->
+ <script type="text/javascript">
+ // e4x is disabled by default, so HTML comments are single-line only.
+ var comment_a = <!--
+ ? /*warning:syntax_error*/
+ -->;
+ </script>
+ <script type="text/javascript;e4x=1">
+ // Explicitly enable e4x.
+ var comment_c = <!--
+ ?
+ -->;
+ </script>
+ <script type="text/javascript;version=1.6;e4x=0">
+ // e4x is always enabled in 1.6+
+ var comment_b = <!--
+ ?
+ -->;
+ </script>
+</head>
+<body>
+</body>
+</html>
Added: trunk/tests/html/unsupported_version.html
===================================================================
--- trunk/tests/html/unsupported_version.html (rev 0)
+++ trunk/tests/html/unsupported_version.html 2010-10-03 20:18:10 UTC (rev 301)
@@ -0,0 +1,19 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
+<html>
+<head>
+ <title>JavaScript Lint Test Page</title>
+ <script type="text/javascript;version=0.1"> /*warning:unsupported_version*/
+ function x() {
+ return 10;
+ }
+ </script>
+ <script language="javascript10.0"> /*warning:unsupported_version*/
+ function x() {
+ return 10;
+ }
+ </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...> - 2013-09-28 03:06:23
|
Revision: 304
http://sourceforge.net/p/javascriptlint/code/304
Author: matthiasmiller
Date: 2013-09-28 03:06:19 +0000 (Sat, 28 Sep 2013)
Log Message:
-----------
Replace SpiderMonkey with a JavaScript parser written purely in JavaScript.
Modified Paths:
--------------
trunk/DEVELOPMENT
trunk/INSTALL
trunk/javascriptlint/jsparse.py
trunk/javascriptlint/lint.py
trunk/javascriptlint/warnings.py
trunk/setup.py
trunk/test.py
trunk/tests/control_comments/conf-version.js
trunk/tests/html/e4x.html
trunk/tests/html/script_tag_in_js_comment.html
trunk/tests/warnings/identifier_hides_another.js
trunk/tests/warnings/spidermonkey/bad_backref.js
trunk/tests/warnings/spidermonkey/invalid_backref.js
trunk/tests/warnings/want_assign_or_call.js
Added Paths:
-----------
trunk/jsengine/
trunk/jsengine/__init__.py
trunk/jsengine/parser/
trunk/jsengine/parser/__init__.py
trunk/jsengine/parser/_constants_kind.py
trunk/jsengine/parser/_constants_op.py
trunk/jsengine/structs.py
trunk/jsengine/tokenizer/
trunk/jsengine/tokenizer/__init__.py
Removed Paths:
-------------
trunk/Makefile.SpiderMonkey
trunk/javascriptlint/pyspidermonkey/
trunk/javascriptlint/pyspidermonkey_/
trunk/javascriptlint/spidermonkey.py
trunk/spidermonkey/
trunk/tests/warnings/spidermonkey/deprecated_usage.js
Modified: trunk/DEVELOPMENT
===================================================================
--- trunk/DEVELOPMENT 2011-12-02 18:49:10 UTC (rev 303)
+++ trunk/DEVELOPMENT 2013-09-28 03:06:19 UTC (rev 304)
@@ -15,17 +15,3 @@
> add test for syntax error
> consider reimplementing abiguous_newline
-
-** UPGRADING SPIDERMONKEY
-
-Use the following command to upgrade SpiderMonkey. Replace X.X.X with the
-version number. js-X.X.X is the directory containing the new version of
-SpiderMonkey. Use a relative path for pretty commit messages.
-
-svn_load_dirs.pl \
- -t X.X.X \
- -p svn_load_dirs.conf \
- https://javascriptlint.svn.sourceforge.net/svnroot/javascriptlint/vendorsrc/Mozilla.org/js \
- current \
- js-X.X.X
-
Modified: trunk/INSTALL
===================================================================
--- trunk/INSTALL 2011-12-02 18:49:10 UTC (rev 303)
+++ trunk/INSTALL 2013-09-28 03:06:19 UTC (rev 304)
@@ -1,14 +1,4 @@
-BUILDING FROM THE SUBVERSION TRUNK
-* Windows Prequisites:
- * Visual Studio 2008 Express
- * Python 2.6
- * py2exe
- * MozillaBuild (http://developer.mozilla.org/en/docs/Windows_Build_Prerequisites)
-
- Launch the MozillaBuild MSVC 9 batch file. (You may have to run this as an
- Administrator on Windows Vista.) Run the commands in that shell.
-
On all platforms:
$ python setup.py build
Deleted: trunk/Makefile.SpiderMonkey
===================================================================
--- trunk/Makefile.SpiderMonkey 2011-12-02 18:49:10 UTC (rev 303)
+++ trunk/Makefile.SpiderMonkey 2013-09-28 03:06:19 UTC (rev 304)
@@ -1,59 +0,0 @@
-## THIS IS AN INTERNAL MAKEFILE FOR setup.py
-## DO NOT RUN THIS MAKEFILE DIRECTLY.
-
-SPIDERMONKEY_SRC=spidermonkey/src
-
-# Load the SpiderMonkey config to find the OS define
-# Also use this for the SO_SUFFIX
-DEPTH=$(SPIDERMONKEY_SRC)
-include $(SPIDERMONKEY_SRC)/config.mk
-SPIDERMONKEY_OS=$(firstword $(patsubst -D%, %, $(filter -DXP_%, $(OS_CFLAGS))))
-
-ifdef USE_MSVC
-JS_LIB=js32.lib
-else
-JS_LIB=libjs.a
-endif
-
-BUILD_DIR=build/spidermonkey
-
-ORIG_LIB=$(SPIDERMONKEY_SRC)/$(OBJDIR)/$(JS_LIB)
-COPY_LIB=$(BUILD_DIR)/$(JS_LIB)
-ORIG_DLL=$(SPIDERMONKEY_SRC)/$(OBJDIR)/js32.dll
-COPY_DLL_DIR=$(DISTUTILS_DIR)/javascriptlint
-COPY_DLL_PATH=$(COPY_DLL_DIR)/js32.dll
-OS_HEADER=$(BUILD_DIR)/js_operating_system.h
-ORIG_JSAUTOCFG_H=$(SPIDERMONKEY_SRC)/$(OBJDIR)/jsautocfg.h
-COPY_JSAUTOCFG_H=$(BUILD_DIR)/jsautocfg.h
-
-ALL_TARGETS=$(COPY_LIB) $(OS_HEADER)
-ifndef PREBUILT_CPUCFG
-ALL_TARGETS+=$(COPY_JSAUTOCFG_H)
-endif
-
-ifeq ($(SPIDERMONKEY_OS),XP_WIN)
-ALL_TARGETS+=$(COPY_DLL_PATH)
-endif
-
-all: $(ALL_TARGETS)
-
-clean:
- rm -f $(ORIG_LIB)
- rm -Rf $(BUILD_DIR)
-
-$(BUILD_DIR):
- mkdir -p $(BUILD_DIR)
-
-$(COPY_LIB): $(BUILD_DIR) $(ORIG_LIB)
- cp $(ORIG_LIB) $(COPY_LIB)
-
-$(COPY_DLL_PATH): $(ORIG_DLL)
- mkdir -p $(COPY_DLL_DIR)
- cp $(ORIG_DLL) $(COPY_DLL_PATH)
-
-$(OS_HEADER): $(BUILD_DIR)
- echo "#define $(SPIDERMONKEY_OS)" > $(OS_HEADER)
-
-$(COPY_JSAUTOCFG_H): $(ORIG_JSAUTOCFG_H)
- cp $(ORIG_JSAUTOCFG_H) $(COPY_JSAUTOCFG_H)
-
Modified: trunk/javascriptlint/jsparse.py
===================================================================
--- trunk/javascriptlint/jsparse.py 2011-12-02 18:49:10 UTC (rev 303)
+++ trunk/javascriptlint/jsparse.py 2013-09-28 03:06:19 UTC (rev 304)
@@ -1,155 +1,20 @@
#!/usr/bin/python
# vim: ts=4 sw=4 expandtab
""" Parses a script into nodes. """
-import bisect
import re
import unittest
-import spidermonkey
-from spidermonkey import tok, op
-from util import JSVersion
+import jsengine.parser
+from jsengine.parser import kind as tok
+from jsengine.parser import op
+from jsengine.structs import *
-_tok_names = dict(zip(
- [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)]
-))
+from .util import JSVersion
-NodePos = spidermonkey.NodePos
-
-class NodePositions:
- " Given a string, allows [x] lookups for NodePos line and column numbers."
- 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)):
- lines[x] += lines[x-1]
- self._line_offsets = lines
- 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):
- self._offsets = []
- def add(self, start, end):
- i = bisect.bisect_left(self._offsets, start)
- if i % 2 == 1:
- i -= 1
- start = self._offsets[i]
-
- end = end + 1
- j = bisect.bisect_left(self._offsets, end)
- if j % 2 == 1:
- end = self._offsets[j]
- j += 1
-
- self._offsets[i:j] = [start,end]
- def has(self, pos):
- return bisect.bisect_right(self._offsets, pos) % 2 == 1
-
-class _Node:
- def add_child(self, node):
- if node:
- node.node_index = len(self.kids)
- node.parent = self
- self.kids.append(node)
-
- def start_pos(self):
- try:
- return self._start_pos
- except AttributeError:
- self._start_pos = NodePos(self._start_line, self._start_col)
- return self._start_pos
-
- def end_pos(self):
- try:
- return self._end_pos
- except AttributeError:
- self._end_pos = NodePos(self._end_line, self._end_col)
- return self._end_pos
-
- def __str__(self):
- kind = self.kind
- if not kind:
- kind = '(none)'
- return '%s>%s' % (_tok_names[kind], str(self.kids))
-
- def is_equivalent(self, other, are_functions_equiv=False):
- if not other:
- return False
-
- # Bail out for functions
- if not are_functions_equiv:
- if self.kind == tok.FUNCTION:
- return False
- if self.kind == tok.LP and self.opcode == op.CALL:
- return False
-
- if self.kind != other.kind:
- return False
- if self.opcode != other.opcode:
- return False
-
- # Check atoms on names, properties, and string constants
- if self.kind in (tok.NAME, tok.DOT, tok.STRING) and self.atom != other.atom:
- return False
-
- # Check values on numbers
- if self.kind == tok.NUMBER and self.dval != other.dval:
- return False
-
- # Compare child nodes
- if len(self.kids) != len(other.kids):
- return False
- for i in range(0, len(self.kids)):
- # Watch for dead nodes
- if not self.kids[i]:
- if not other.kids[i]: return True
- else: return False
- if not self.kids[i].is_equivalent(other.kids[i]):
- return False
-
- return True
-
def isvalidversion(jsversion):
if jsversion is None:
return True
- return spidermonkey.is_valid_version(jsversion.version)
+ return jsengine.parser.is_valid_version(jsversion.version)
def findpossiblecomments(script, node_positions):
pos = 0
@@ -168,31 +33,18 @@
comment_text = script[match.start():match.end()]
if comment_text.startswith('/*'):
comment_text = comment_text[2:-2]
- opcode = 'JSOP_C_COMMENT'
+ opcode = op.C_COMMENT
else:
comment_text = comment_text[2:]
- opcode = 'JSOP_CPP_COMMENT'
- opcode = opcode[5:].lower()
+ opcode = op.CPP_COMMENT
start_offset = match.start()
end_offset = match.end()-1
start_pos = node_positions.from_offset(start_offset)
end_pos = node_positions.from_offset(end_offset)
- kwargs = {
- 'kind': '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)
+ comment_node = ParseNode(kind.COMMENT, opcode, start_pos, end_pos,
+ comment_text, [])
comments.append(comment_node)
# Start searching immediately after the start of the comment in case
@@ -203,28 +55,23 @@
""" 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)
-
startpos = startpos or NodePos(0,0)
jsversion = jsversion or JSVersion.default()
- assert isvalidversion(jsversion)
- return spidermonkey.parse(script, jsversion.version, jsversion.e4x,
- _Node, _wrapped_callback,
- startpos.line, startpos.col)
+ assert isvalidversion(jsversion), jsversion
+ if jsversion.e4x:
+ error_callback(startpos.line, startpos.col, 'e4x_deprecated', {})
+ return jsengine.parser.parse(script, jsversion.version,
+ error_callback,
+ startpos)
def filtercomments(possible_comments, node_positions, root_node):
comment_ignore_ranges = NodeRanges()
def process(node):
- if node.kind == tok.NUMBER:
- node.atom = node_positions.text(node.start_pos(), node.end_pos())
- elif node.kind == tok.STRING or \
+ if node.kind == tok.STRING or \
(node.kind == tok.OBJECT and node.opcode == op.REGEXP):
start_offset = node_positions.to_offset(node.start_pos())
- end_offset = node_positions.to_offset(node.end_pos()) - 1
+ end_offset = node_positions.to_offset(node.end_pos())
comment_ignore_ranges.add(start_offset, end_offset)
for kid in node.kids:
if kid:
@@ -249,7 +96,7 @@
def is_compilable_unit(script, jsversion):
jsversion = jsversion or JSVersion.default()
assert isvalidversion(jsversion)
- return spidermonkey.is_compilable_unit(script, jsversion.version, jsversion.e4x)
+ return jsengine.parser.is_compilable_unit(script, jsversion.version)
def _dump_node(node, depth=0):
if node is None:
@@ -258,7 +105,7 @@
print
else:
print ' '*depth,
- print '%s, %s' % (_tok_names[node.kind], _op_names[node.opcode])
+ print '%s, %s' % (repr(node.kind), repr(node.opcode))
print ' '*depth,
print '%s - %s' % (node.start_pos(), node.end_pos())
if hasattr(node, 'atom'):
@@ -379,22 +226,21 @@
for text, expected in tests:
encountered = is_compilable_unit(text, JSVersion.default())
self.assertEquals(encountered, expected)
- # NOTE: This seems like a bug.
- self.assert_(is_compilable_unit("/* test", JSVersion.default()))
+ self.assert_(not is_compilable_unit("/* test", JSVersion.default()))
class TestLineOffset(unittest.TestCase):
def testErrorPos(self):
def geterror(script, startpos):
errors = []
- def onerror(line, col, msg):
- errors.append((line, col, msg))
+ def onerror(line, col, msg, msg_args):
+ errors.append((line, col, msg, msg_args))
parse(script, None, 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'))
+ 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, None, startpos)
Modified: trunk/javascriptlint/lint.py
===================================================================
--- trunk/javascriptlint/lint.py 2011-12-02 18:49:10 UTC (rev 303)
+++ trunk/javascriptlint/lint.py 2013-09-28 03:06:19 UTC (rev 304)
@@ -12,7 +12,8 @@
import unittest
import util
-from spidermonkey import tok, op
+from jsengine.parser import kind as tok
+from jsengine.parser import op
_newline_kinds = (
'eof', 'comma', 'dot', 'semi', 'colon', 'lc', 'rc', 'lp', 'rb', 'assign',
@@ -96,6 +97,7 @@
def add_declaration(self, name, node, type_):
assert type_ in ('arg', 'function', 'var'), \
'Unrecognized identifier type: %s' % type_
+ assert isinstance(name, basestring)
self._identifiers[name] = {
'node': node,
'type': type_
@@ -339,10 +341,10 @@
def _lint_script_part(scriptpos, jsversion, script, script_cache, conf,
ignores, report_native, report_lint, import_callback):
- def parse_error(row, col, msg):
+ def parse_error(row, col, msg, msg_args):
if not msg in ('anon_no_return_value', 'no_return_value',
'redeclared_var', 'var_hides_arg'):
- parse_errors.append((jsparse.NodePos(row, col), msg))
+ parse_errors.append((jsparse.NodePos(row, col), msg, msg_args))
def report(node, errname, pos=None, **errargs):
if errname == 'empty_statement' and node.kind == tok.LC:
@@ -411,8 +413,8 @@
root = jsparse.parse(script, jsversion, parse_error, scriptpos)
if not root:
# Report errors and quit.
- for pos, msg in parse_errors:
- report_native(pos, msg)
+ for pos, msg, msg_args in parse_errors:
+ report_native(pos, msg, msg_args)
return
comments = jsparse.filtercomments(possible_comments, node_positions, root)
@@ -457,7 +459,7 @@
elif keyword == 'pass':
passes.append(node)
else:
- if comment.opcode == 'c_comment':
+ if comment.opcode == op.C_COMMENT:
# Look for nested C-style comments.
nested_comment = comment.atom.find('/*')
if nested_comment < 0 and comment.atom.endswith('/'):
@@ -514,9 +516,9 @@
errdesc = warnings.format_error(errname, **errargs)
_report(pos or node.start_pos(), errname, errdesc, True)
- def report_native(pos, errname):
- # TODO: Format the error.
- _report(pos, errname, errname, False)
+ def report_native(pos, errname, errargs):
+ errdesc = warnings.format_error(errname, **errargs)
+ _report(pos, errname, errdesc, False)
def _report(pos, errname, errdesc, require_key):
try:
@@ -581,7 +583,7 @@
if other and parent_scope == scope:
# Only warn about duplications in this scope.
# Other scopes will be checked later.
- if other.kind == tok.FUNCTION and name in other.fn_args:
+ if other.kind == tok.NAME and other.opcode == op.ARGNAME:
report(node, 'var_hides_arg', name=name)
else:
report(node, 'redeclared_var', name=name)
@@ -612,7 +614,9 @@
_warn_or_declare(scopes[-1], node.fn_name, 'function', node, report)
self._push_scope(node)
for var_name in node.fn_args:
- scopes[-1].add_declaration(var_name, node, 'arg')
+ if scopes[-1].get_identifier(var_name.atom):
+ report(var_name, 'duplicate_formal', name=var_name.atom)
+ scopes[-1].add_declaration(var_name.atom, var_name, 'arg')
@visitation.visit('push', tok.LEXICALSCOPE, tok.WITH)
def _push_scope(self, node):
Deleted: trunk/javascriptlint/spidermonkey.py
===================================================================
--- trunk/javascriptlint/spidermonkey.py 2011-12-02 18:49:10 UTC (rev 303)
+++ trunk/javascriptlint/spidermonkey.py 2013-09-28 03:06:19 UTC (rev 304)
@@ -1,10 +0,0 @@
-# vim: ts=4 sw=4 expandtab
-
-# This is a wrapper script to make it easier for development. It tries to
-# import the development version first, and if that fails, it goes after the
-# real version.
-try:
- from pyspidermonkey_ import *
-except ImportError:
- from pyspidermonkey import *
-
Modified: trunk/javascriptlint/warnings.py
===================================================================
--- trunk/javascriptlint/warnings.py 2011-12-02 18:49:10 UTC (rev 303)
+++ trunk/javascriptlint/warnings.py 2013-09-28 03:06:19 UTC (rev 304)
@@ -21,9 +21,10 @@
import util
import visitation
-from spidermonkey import tok, op
+from jsengine.parser import kind as tok
+from jsengine.parser import op
-_ALL_TOKENS = tuple(filter(lambda x: x != tok.EOF, tok.__dict__.values()))
+_ALL_TOKENS = tok.__dict__.values()
def _get_assigned_lambda(node):
""" Given a node "x = function() {}", returns "function() {}".
@@ -53,6 +54,7 @@
'use_of_label': 'use of label',
'misplaced_regex': 'regular expressions should be preceded by a left parenthesis, assignment, colon, or comma',
'assign_to_function_call': 'assignment to a function call',
+ 'equal_as_assign': 'test for equality (==) mistyped as assignment (=)?',
'ambiguous_else_stmt': 'the else statement could be matched with one of multiple if statements (use curly braces to indicate intent',
'block_without_braces': 'block statement without curly braces',
'ambiguous_nested_stmt': 'block statements containing block statements should use curly braces to resolve ambiguity',
@@ -70,6 +72,7 @@
'leading_decimal_point': 'leading decimal point may indicate a number or an object member',
'trailing_decimal_point': 'trailing decimal point may indicate a number or an object member',
'octal_number': 'leading zeros make an octal number',
+ 'trailing_comma': 'extra comma is not recommended in object initializers',
'trailing_comma_in_array': 'extra comma is not recommended in array initializers',
'useless_quotes': 'the quotation marks are unnecessary',
'mismatch_ctrl_comments': 'mismatched control comment; "ignore" and "end" control comments must have a one-to-one correspondence',
@@ -99,8 +102,20 @@
'incorrect_version': 'Expected /*jsl:content-type*/ control comment. The script was parsed with the wrong version.',
}
+errors = {
+ 'e4x_deprecated': 'e4x is deprecated',
+ 'semi_before_stmnt': 'missing semicolon before statement',
+ 'syntax_error': 'syntax error',
+ 'expected_tok': 'expected token: {token}',
+ 'unexpected_char': 'unexpected character: {char}',
+}
+
def format_error(errname, **errargs):
- errdesc = warnings[errname]
+ if errname in errors:
+ errdesc = errors[errname]
+ else:
+ errdesc = warnings[errname]
+
try:
errdesc = re.sub(r"{(\w+)}", lambda match: errargs[match.group(1)], errdesc)
except (TypeError, KeyError):
@@ -295,9 +310,18 @@
@lookfor(tok.ASSIGN)
def assign_to_function_call(node):
- if node.kids[0].kind == tok.LP:
+ kid = node.kids[0]
+ # Unpack parens.
+ while kid.kind == tok.RP:
+ kid, = kid.kids
+ if kid.kind == tok.LP:
raise LintWarning, node
+@lookfor(tok.ASSIGN)
+def equal_as_assign(node):
+ if not node.parent.kind in (tok.SEMI, tok.RESERVED, tok.RP, tok.COMMA):
+ raise LintWarning, node
+
@lookfor(tok.IF)
def ambiguous_else_stmt(node):
# Only examine this node if it has an else statement.
@@ -492,6 +516,11 @@
if _octal_regexp.match(node.atom):
raise LintWarning, node
+@lookfor(tok.RC)
+def trailing_comma(node):
+ if node.end_comma:
+ raise LintWarning, node
+
@lookfor(tok.RB)
def trailing_comma_in_array(node):
if node.end_comma:
Index: trunk/jsengine
===================================================================
--- trunk/jsengine 2011-12-02 18:49:10 UTC (rev 303)
+++ trunk/jsengine 2013-09-28 03:06:19 UTC (rev 304)
Property changes on: trunk/jsengine
___________________________________________________________________
Added: svn:ignore
## -0,0 +1 ##
+*.pyc
Added: trunk/jsengine/__init__.py
===================================================================
--- trunk/jsengine/__init__.py (rev 0)
+++ trunk/jsengine/__init__.py 2013-09-28 03:06:19 UTC (rev 304)
@@ -0,0 +1,21 @@
+# vim: sw=4 ts=4 et
+
+_MESSAGES = (
+ 'eof',
+ 'semi_before_stmnt',
+ 'syntax_error',
+ 'unterminated_comment',
+ 'expected_tok',
+ 'unexpected_char',
+)
+
+class JSSyntaxError(BaseException):
+ def __init__(self, pos, msg, msg_args=None):
+ assert msg in _MESSAGES, msg
+ self.pos = pos
+ self.msg = msg
+ self.msg_args = msg_args or {}
+ def __unicode__(self):
+ return '%s: %s' % (self.pos, self.msg)
+ def __repr__(self):
+ return 'JSSyntaxError(%r, %r, %r)' % (self.pos, self.msg. self.msg_args)
Added: trunk/jsengine/parser/__init__.py
===================================================================
--- trunk/jsengine/parser/__init__.py (rev 0)
+++ trunk/jsengine/parser/__init__.py 2013-09-28 03:06:19 UTC (rev 304)
@@ -0,0 +1,924 @@
+# vim: sw=4 ts=4 et
+import unittest
+
+from jsengine.tokenizer import tok
+from jsengine import tokenizer
+
+from jsengine import JSSyntaxError
+from _constants_kind import kind
+from _constants_op import op
+
+from jsengine.structs import *
+
+_VERSIONS = [
+ "default",
+ "1.0",
+ "1.1",
+ "1.2",
+ "1.3",
+ "1.4",
+ "1.5",
+ "1.6",
+ "1.7",
+]
+
+def _auto_semicolon(t, kind_, op_, startpos, endpos, atom, kids):
+ nosemi = False
+ if t.peek_sameline().tok not in (tok.EOF, tok.EOL, tok.RBRACE):
+ x = t.advance()
+ if x.tok != tok.SEMI:
+ raise JSSyntaxError(x.startpos, 'semi_before_stmnt')
+ endpos = x.endpos
+ else:
+ nosemi = True
+ return ParseNode(kind_, op_, startpos, endpos, atom, kids, nosemi)
+
+def _function_arglist(t):
+ fn_args = []
+ if t.peek().tok != tok.RPAREN:
+ while True:
+ x = t.expect(tok.NAME)
+ fn_args.append(ParseNode(kind.NAME, op.ARGNAME,
+ x.startpos,
+ x.endpos, x.atom, []))
+ if t.peek().tok == tok.COMMA:
+ t.advance()
+ else:
+ break
+ return fn_args
+
+def _primary_expression(t):
+ x = t.next_withregexp()
+ if x.tok == tok.THIS:
+ return ParseNode(kind.PRIMARY, op.THIS, x.startpos, x.endpos, None, [])
+ elif x.tok == tok.NAME:
+ return ParseNode(kind.NAME, op.NAME, x.startpos, x.endpos, x.atom, [None])
+ elif x.tok == tok.NULL:
+ return ParseNode(kind.PRIMARY, op.NULL, x.startpos, x.endpos, None, [])
+ elif x.tok == tok.TRUE:
+ return ParseNode(kind.PRIMARY, op.TRUE, x.startpos, x.endpos, None, [])
+ elif x.tok == tok.FALSE:
+ return ParseNode(kind.PRIMARY, op.FALSE, x.startpos, x.endpos, None, [])
+ elif x.tok == tok.STRING:
+ return ParseNode(kind.STRING, op.STRING, x.startpos, x.endpos, x.atom, [])
+ elif x.tok == tok.REGEXP:
+ return ParseNode(kind.OBJECT, op.REGEXP, x.startpos, x.endpos, None, [])
+ elif x.tok == tok.NUMBER:
+ return ParseNode(kind.NUMBER, None, x.startpos, x.endpos, x.atom, [])
+ elif x.tok == tok.LBRACKET:
+ startpos = x.startpos
+ items = []
+ end_comma = None
+ if t.peek().tok != tok.RBRACKET:
+ while True:
+ # Conditionally add a value. If it isn't followed by a comma,
+ # quit in order to force an RBRACKET.
+ if t.peek().tok == tok.COMMA:
+ items.append(None)
+ else:
+ items.append(_assignment_expression(t, True))
+ if not t.peek().tok == tok.COMMA:
+ break
+
+ # Expect a comma and use it if the value was missing.
+ x = t.expect(tok.COMMA)
+ comma = ParseNode(kind.COMMA, None,
+ x.startpos, x.endpos, None, [])
+ items[-1] = items[-1] or comma
+
+ # Check for the end.
+ if t.peek().tok == tok.RBRACKET:
+ end_comma = comma
+ break
+ endpos = t.expect(tok.RBRACKET).endpos
+ return ParseNode(kind.RB, None, startpos, endpos, None, items,
+ end_comma=end_comma)
+ elif x.tok == tok.LBRACE:
+ startpos = x.startpos
+ kids = []
+ # TODO: get/set
+ end_comma = None
+ while True:
+ x = t.peek()
+ if x.tok == tok.RBRACE:
+ break
+ elif x.tok == tok.STRING:
+ t.expect(tok.STRING)
+ key = ParseNode(kind.STRING, None, x.startpos,
+ x.endpos, x.atom, [])
+ elif x.tok == tok.NUMBER:
+ t.expect(tok.NUMBER)
+ key = ParseNode(kind.NUMBER, None, x.startpos,
+ x.endpos, x.atom, [])
+ else:
+ x = t.expect_identifiername()
+ key = ParseNode(kind.NAME, None, x.startpos, x.endpos,
+ x.atom, [])
+ t.expect(tok.COLON)
+ value = _assignment_expression(t, True)
+ kids.append(ParseNode(kind.COLON, None, key.startpos,
+ value.endpos, None, [key, value]))
+ if t.peek().tok == tok.COMMA:
+ x = t.advance()
+ end_comma = ParseNode(kind.COMMA, None,
+ x.startpos, x.endpos, None, [])
+ else:
+ end_comma = None
+ break
+ endpos = t.expect(tok.RBRACE).endpos
+ return ParseNode(kind.RC, None, startpos, endpos, None, kids,
+ end_comma=end_comma)
+ elif x.tok == tok.LPAREN:
+ startpos = x.startpos
+ kid = _expression(t, True)
+ endpos = t.expect(tok.RPAREN).endpos
+ return ParseNode(kind.RP, None, startpos, endpos, None, [kid])
+ else:
+ raise JSSyntaxError(x.startpos, 'syntax_error')
+
+def _function_declaration(t, named_opcode):
+ node = _function_expression(t, named_opcode)
+
+ # Convert anonymous functions in expressions.
+ if node.opcode == op.ANONFUNOBJ:
+ node = _auto_semicolon(t, kind.SEMI, None, node.startpos, node.endpos,
+ None, [node])
+ return node
+
+
+def _function_expression(t, named_opcode):
+ startpos = t.expect(tok.FUNCTION).startpos
+ if t.peek().tok == tok.NAME:
+ fn_name = t.expect(tok.NAME).atom
+ opcode = named_opcode
+ else:
+ fn_name = None
+ opcode = op.ANONFUNOBJ
+ t.expect(tok.LPAREN)
+ fn_args = _...
[truncated message content] |
|
From: <mat...@us...> - 2013-09-28 03:38:26
|
Revision: 305
http://sourceforge.net/p/javascriptlint/code/305
Author: matthiasmiller
Date: 2013-09-28 03:38:24 +0000 (Sat, 28 Sep 2013)
Log Message:
-----------
#41 python re-write doesn't support option explicit Move Edit
Fix traceback mentioned in comment regarding invalid control comments
Modified Paths:
--------------
trunk/javascriptlint/lint.py
trunk/tests/control_comments/control_comments.js
Modified: trunk/javascriptlint/lint.py
===================================================================
--- trunk/javascriptlint/lint.py 2013-09-28 03:06:19 UTC (rev 304)
+++ trunk/javascriptlint/lint.py 2013-09-28 03:38:24 UTC (rev 305)
@@ -54,29 +54,28 @@
control_comment = comment.atom[1:-1]
else:
return None
+ control_comment = control_comment.lower().rstrip()
- control_comments = {
- 'ignoreall': (False),
- 'ignore': (False),
- 'end': (False),
- 'option explicit': (False),
- 'import': (True),
- 'fallthru': (False),
- 'pass': (False),
- 'declare': (True),
- 'unused': (True),
- 'content-type': (True),
- }
- if control_comment.lower() in control_comments:
- keyword = control_comment.lower()
- else:
- keyword = control_comment.lower().split()[0]
- if not keyword in control_comments:
- return None
+ keywords = (
+ 'ignoreall',
+ 'ignore',
+ 'end',
+ 'option explicit',
+ 'import',
+ 'fallthru',
+ 'pass',
+ 'declare',
+ 'unused',
+ 'content-type',
+ )
+ for keyword in keywords:
+ # The keyword must either match or be separated by a space.
+ if control_comment == keyword or \
+ (control_comment.startswith(keyword) and \
+ control_comment[len(keyword)].isspace()):
+ parms = control_comment[len(keyword):].strip()
+ return (comment, keyword, parms.strip())
- parms = control_comment[len(keyword):].strip()
- return (comment, keyword, parms)
-
class Scope:
""" Outer-level scopes will never be associated with a node.
Inner-level scopes will always be associated with a node.
Modified: trunk/tests/control_comments/control_comments.js
===================================================================
--- trunk/tests/control_comments/control_comments.js 2013-09-28 03:06:19 UTC (rev 304)
+++ trunk/tests/control_comments/control_comments.js 2013-09-28 03:38:24 UTC (rev 305)
@@ -29,5 +29,15 @@
/* illegal - don't forget to end */
/*jsl:ignore*/ /*warning:mismatch_ctrl_comments*/
+
+ // The following are illegal. Make sure jsl doesn't choke.
+ /*jsl:*/ /*warning:jsl_cc_not_understood*/
+ if (a)
+ {
+ /*jsl:pass */
+ }
+ /*jsl:ignoreal*/ /*warning:jsl_cc_not_understood*/
+ /*jsl:declarebogus*/ /*warning:jsl_cc_not_understood*/
+ /*jsl:declare bogus */
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mat...@us...> - 2013-09-28 03:45:40
|
Revision: 306
http://sourceforge.net/p/javascriptlint/code/306
Author: matthiasmiller
Date: 2013-09-28 03:45:38 +0000 (Sat, 28 Sep 2013)
Log Message:
-----------
#45 jsl: declarations should allow for surrounding spaces
Modified Paths:
--------------
trunk/javascriptlint/lint.py
trunk/tests/control_comments/control_comments.js
Modified: trunk/javascriptlint/lint.py
===================================================================
--- trunk/javascriptlint/lint.py 2013-09-28 03:38:24 UTC (rev 305)
+++ trunk/javascriptlint/lint.py 2013-09-28 03:45:38 UTC (rev 306)
@@ -48,13 +48,13 @@
def _parse_control_comment(comment):
""" Returns None or (keyword, parms) """
- if comment.atom.lower().startswith('jsl:'):
- control_comment = comment.atom[4:]
- elif comment.atom.startswith('@') and comment.atom.endswith('@'):
- control_comment = comment.atom[1:-1]
+ comment_atom = comment.atom.lower().strip()
+ if comment_atom.startswith('jsl:'):
+ control_comment = comment_atom[4:]
+ elif comment_atom.startswith('@') and comment_atom.endswith('@'):
+ control_comment = comment_atom[1:-1]
else:
return None
- control_comment = control_comment.lower().rstrip()
keywords = (
'ignoreall',
Modified: trunk/tests/control_comments/control_comments.js
===================================================================
--- trunk/tests/control_comments/control_comments.js 2013-09-28 03:38:24 UTC (rev 305)
+++ trunk/tests/control_comments/control_comments.js 2013-09-28 03:45:38 UTC (rev 306)
@@ -32,10 +32,12 @@
// The following are illegal. Make sure jsl doesn't choke.
/*jsl:*/ /*warning:jsl_cc_not_understood*/
- if (a)
- {
+ if (a) {
/*jsl:pass */
}
+ else if (b) {
+ /* jsl:pass */ //allow spaces on both sides
+ }
/*jsl:ignoreal*/ /*warning:jsl_cc_not_understood*/
/*jsl:declarebogus*/ /*warning:jsl_cc_not_understood*/
/*jsl:declare bogus */
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mat...@us...> - 2013-09-28 04:08:33
|
Revision: 308
http://sourceforge.net/p/javascriptlint/code/308
Author: matthiasmiller
Date: 2013-09-28 04:08:31 +0000 (Sat, 28 Sep 2013)
Log Message:
-----------
#42 Failure when input file is not utf-8 encoded
Allow passing the input file encoding on the command line.
Modified Paths:
--------------
trunk/javascriptlint/conf.py
trunk/javascriptlint/fs.py
trunk/javascriptlint/jsl.py
trunk/javascriptlint/lint.py
trunk/test.py
Modified: trunk/javascriptlint/conf.py
===================================================================
--- trunk/javascriptlint/conf.py 2013-09-28 03:50:06 UTC (rev 307)
+++ trunk/javascriptlint/conf.py 2013-09-28 04:08:31 UTC (rev 308)
@@ -187,7 +187,7 @@
def loadfile(self, path):
path = os.path.abspath(path)
- conf = fs.readfile(path)
+ conf = fs.readfile(path, 'utf-8')
try:
self.loadtext(conf, dir=os.path.dirname(path))
except ConfError, error:
Modified: trunk/javascriptlint/fs.py
===================================================================
--- trunk/javascriptlint/fs.py 2013-09-28 03:50:06 UTC (rev 307)
+++ trunk/javascriptlint/fs.py 2013-09-28 04:08:31 UTC (rev 308)
@@ -2,8 +2,8 @@
import codecs
import os
-def readfile(path):
- file = codecs.open(path, 'r', 'utf-8')
+def readfile(path, encoding):
+ file = codecs.open(path, 'r', encoding)
contents = file.read()
if contents and contents[0] == unicode(codecs.BOM_UTF8, 'utf8'):
contents = contents[1:]
Modified: trunk/javascriptlint/jsl.py
===================================================================
--- trunk/javascriptlint/jsl.py 2013-09-28 03:50:06 UTC (rev 307)
+++ trunk/javascriptlint/jsl.py 2013-09-28 04:08:31 UTC (rev 308)
@@ -20,17 +20,17 @@
'errors': 0
}
-def _dump(paths):
+def _dump(paths, encoding):
for path in paths:
- script = fs.readfile(path)
+ script = fs.readfile(path, encoding)
jsparse.dump_tree(script)
-def _lint(paths, conf_, printpaths):
+def _lint(paths, conf_, printpaths, encoding):
def lint_error(path, line, col, errname, errdesc):
_lint_results['warnings'] = _lint_results['warnings'] + 1
print util.format_error(conf_['output-format'], path, line, col,
errname, errdesc)
- lint.lint_files(paths, lint_error, conf=conf_, printpaths=printpaths)
+ lint.lint_files(paths, lint_error, encoding, conf=conf_, printpaths=printpaths)
def _resolve_paths(path, recurse):
# Build a list of directories
@@ -97,6 +97,8 @@
help="suppress lint summary")
add("--help:conf", dest="showdefaultconf", action="store_true", default=False,
help="display the default configuration file")
+ add("--encoding", dest="encoding", metavar="ENCODING", default="utf-8",
+ help="encoding for input file(s)")
parser.set_defaults(verbosity=1)
options, args = parser.parse_args()
@@ -138,9 +140,9 @@
else:
paths.append(arg)
if options.dump:
- profile_func(_dump, paths)
+ profile_func(_dump, paths, options.encoding)
else:
- profile_func(_lint, paths, conf_, options.printlisting)
+ profile_func(_lint, paths, conf_, options.printlisting, options.encoding)
if options.printsummary:
print '\n%i error(s), %i warnings(s)' % (_lint_results['errors'],
Modified: trunk/javascriptlint/lint.py
===================================================================
--- trunk/javascriptlint/lint.py 2013-09-28 03:50:06 UTC (rev 307)
+++ trunk/javascriptlint/lint.py 2013-09-28 04:08:31 UTC (rev 308)
@@ -286,14 +286,14 @@
else:
assert False, 'Invalid internal tag type %s' % tag['type']
-def lint_files(paths, lint_error, conf=conf.Conf(), printpaths=True):
- def lint_file(path, kind, jsversion):
+def lint_files(paths, lint_error, encoding, conf=conf.Conf(), printpaths=True):
+ def lint_file(path, kind, jsversion, encoding):
def import_script(import_path, jsversion):
# The user can specify paths using backslashes (such as when
# linting Windows scripts on a posix environment.
import_path = import_path.replace('\\', os.sep)
import_path = os.path.join(os.path.dirname(path), import_path)
- return lint_file(import_path, 'js', jsversion)
+ return lint_file(import_path, 'js', jsversion, encoding)
def _lint_error(*args):
return lint_error(normpath, *args)
@@ -302,7 +302,7 @@
return lint_cache[normpath]
if printpaths:
print normpath
- contents = fs.readfile(path)
+ contents = fs.readfile(path, encoding)
lint_cache[normpath] = _Script()
script_parts = []
@@ -334,9 +334,9 @@
for path in paths:
ext = os.path.splitext(path)[1]
if ext.lower() in ['.htm', '.html']:
- lint_file(path, 'html', None)
+ lint_file(path, 'html', None, encoding)
else:
- lint_file(path, 'js', None)
+ lint_file(path, 'js', None, encoding)
def _lint_script_part(scriptpos, jsversion, script, script_cache, conf,
ignores, report_native, report_lint, import_callback):
Modified: trunk/test.py
===================================================================
--- trunk/test.py 2013-09-28 03:50:06 UTC (rev 307)
+++ trunk/test.py 2013-09-28 04:08:31 UTC (rev 308)
@@ -61,7 +61,7 @@
else:
unexpected_warnings.append(warning + (errdesc,))
- javascriptlint.lint.lint_files([path], lint_error, conf=conf)
+ javascriptlint.lint.lint_files([path], lint_error, 'utf-8', conf=conf)
errors = []
if expected_warnings:
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mat...@us...> - 2013-09-28 04:17:43
|
Revision: 309
http://sourceforge.net/p/javascriptlint/code/309
Author: matthiasmiller
Date: 2013-09-28 04:17:38 +0000 (Sat, 28 Sep 2013)
Log Message:
-----------
#39 require variable names in "for .. in" statements
Modified Paths:
--------------
trunk/javascriptlint/warnings.py
Added Paths:
-----------
trunk/tests/warnings/for_in_missing_identifier.js
Modified: trunk/javascriptlint/warnings.py
===================================================================
--- trunk/javascriptlint/warnings.py 2013-09-28 04:08:31 UTC (rev 308)
+++ trunk/javascriptlint/warnings.py 2013-09-28 04:17:38 UTC (rev 309)
@@ -100,6 +100,7 @@
'anon_no_return_value': 'anonymous function does not always return value',
'unsupported_version': 'JavaScript {version} is not supported',
'incorrect_version': 'Expected /*jsl:content-type*/ control comment. The script was parsed with the wrong version.',
+ 'for_in_missing_identifier': 'for..in should have identifier on left side',
}
errors = {
@@ -587,6 +588,13 @@
if not node.fn_name:
_check_return_value(node)
+@lookfor((tok.FOR, op.FORIN))
+def for_in_missing_identifier(node):
+ assert node.kids[0].kind == tok.IN
+ left, right = node.kids[0].kids
+ if not left.kind in (tok.VAR, tok.NAME):
+ raise LintWarning, left
+
@lookfor()
def mismatch_ctrl_comments(node):
pass
Added: trunk/tests/warnings/for_in_missing_identifier.js
===================================================================
--- trunk/tests/warnings/for_in_missing_identifier.js (rev 0)
+++ trunk/tests/warnings/for_in_missing_identifier.js 2013-09-28 04:17:38 UTC (rev 309)
@@ -0,0 +1,12 @@
+/*jsl:option explicit*/
+function for_in_missing_identifier(o) {
+ var prop;
+ for (prop in o)
+ o[prop]++;
+
+ for (var prop2 in o)
+ o[prop2]++;
+
+ for (!prop in o) /*warning:for_in_missing_identifier*/
+ o[prop]++;
+}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mat...@us...> - 2013-09-28 04:30:14
|
Revision: 311
http://sourceforge.net/p/javascriptlint/code/311
Author: matthiasmiller
Date: 2013-09-28 04:30:11 +0000 (Sat, 28 Sep 2013)
Log Message:
-----------
Show test results when complete.
Modified Paths:
--------------
trunk/test.py
trunk/tests/warnings/for_in_missing_identifier.js
Modified: trunk/test.py
===================================================================
--- trunk/test.py 2013-09-28 04:27:44 UTC (rev 310)
+++ trunk/test.py 2013-09-28 04:30:11 UTC (rev 311)
@@ -100,6 +100,11 @@
except TestError, error:
haderrors = True
print error
+
+ if haderrors:
+ print '\nOne or more tests failed!'
+ else:
+ print '\nAll tests passed successfully.'
sys.exit(haderrors)
if __name__ == '__main__':
Modified: trunk/tests/warnings/for_in_missing_identifier.js
===================================================================
--- trunk/tests/warnings/for_in_missing_identifier.js 2013-09-28 04:27:44 UTC (rev 310)
+++ trunk/tests/warnings/for_in_missing_identifier.js 2013-09-28 04:30:11 UTC (rev 311)
@@ -1,12 +1,12 @@
/*jsl:option explicit*/
function for_in_missing_identifier(o) {
- var prop;
- for (prop in o)
- o[prop]++;
-
- for (var prop2 in o)
- o[prop2]++;
+ var prop;
+ for (prop in o)
+ o[prop]++;
+
+ for (var prop2 in o)
+ o[prop2]++;
- for (!prop in o) /*warning:for_in_missing_identifier*/
- o[prop]++;
+ for (!prop in o) /*warning:for_in_missing_identifier*/
+ o[prop]++;
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mat...@us...> - 2013-09-28 04:44:08
|
Revision: 312
http://sourceforge.net/p/javascriptlint/code/312
Author: matthiasmiller
Date: 2013-09-28 04:44:05 +0000 (Sat, 28 Sep 2013)
Log Message:
-----------
#38 case with continue results in 'missing break statement'
Treat CONTINUE as an exit point
Modified Paths:
--------------
trunk/javascriptlint/warnings.py
trunk/tests/warnings/missing_break.js
Modified: trunk/javascriptlint/warnings.py
===================================================================
--- trunk/javascriptlint/warnings.py 2013-09-28 04:30:11 UTC (rev 311)
+++ trunk/javascriptlint/warnings.py 2013-09-28 04:44:05 UTC (rev 312)
@@ -202,6 +202,8 @@
exit_points.add(None)
elif node.kind == tok.BREAK:
exit_points = set([node])
+ elif node.kind == tok.CONTINUE:
+ exit_points = set([node])
elif node.kind == tok.WITH:
exit_points = _get_exit_points(node.kids[-1])
elif node.kind == tok.RETURN:
Modified: trunk/tests/warnings/missing_break.js
===================================================================
--- trunk/tests/warnings/missing_break.js 2013-09-28 04:30:11 UTC (rev 311)
+++ trunk/tests/warnings/missing_break.js 2013-09-28 04:44:05 UTC (rev 312)
@@ -102,5 +102,18 @@
break;
}
+ for (;;) {
+ switch(i) {
+ case 1:
+ i++;
+ continue;
+ case 2:
+ if (i)
+ continue;
+ default: /*warning:missing_break*/
+ break;
+ }
+ }
+
return "";
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mat...@us...> - 2013-09-28 05:00:33
|
Revision: 315
http://sourceforge.net/p/javascriptlint/code/315
Author: matthiasmiller
Date: 2013-09-28 05:00:30 +0000 (Sat, 28 Sep 2013)
Log Message:
-----------
Warn against multiple useless comparison (e.g. a == a == b)
Modified Paths:
--------------
trunk/javascriptlint/warnings.py
trunk/tests/warnings/useless_comparison.js
Modified: trunk/javascriptlint/warnings.py
===================================================================
--- trunk/javascriptlint/warnings.py 2013-09-28 04:50:25 UTC (rev 314)
+++ trunk/javascriptlint/warnings.py 2013-09-28 05:00:30 UTC (rev 315)
@@ -14,6 +14,7 @@
if questionable:
raise LintWarning, node
"""
+import itertools
import re
import sys
import types
@@ -287,9 +288,9 @@
@lookfor(tok.EQOP,tok.RELOP)
def useless_comparison(node):
- lvalue, rvalue = node.kids
- if lvalue.is_equivalent(rvalue):
- raise LintWarning, node
+ for lvalue, rvalue in itertools.combinations(node.kids, 2):
+ if lvalue.is_equivalent(rvalue):
+ raise LintWarning, node
@lookfor((tok.COLON, op.NAME))
def use_of_label(node):
Modified: trunk/tests/warnings/useless_comparison.js
===================================================================
--- trunk/tests/warnings/useless_comparison.js 2013-09-28 04:50:25 UTC (rev 314)
+++ trunk/tests/warnings/useless_comparison.js 2013-09-28 05:00:30 UTC (rev 315)
@@ -52,4 +52,12 @@
if (useless_comparison() == useless_comparison()) {
return;
}
+
+ // Test multiple comparisons.
+ if (i == i == 3) /*warning:useless_comparison*/
+ return;
+ if (i == 3 == i) /*warning:useless_comparison*/
+ return;
+ if (i == 3 == j == 3) /*warning:useless_comparison*/
+ return;}
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mat...@us...> - 2013-09-28 19:39:24
|
Revision: 316
http://sourceforge.net/p/javascriptlint/code/316
Author: matthiasmiller
Date: 2013-09-28 19:39:16 +0000 (Sat, 28 Sep 2013)
Log Message:
-----------
Fix unexpected-eof warning.
Modified Paths:
--------------
trunk/javascriptlint/warnings.py
trunk/jsengine/__init__.py
trunk/jsengine/parser/__init__.py
trunk/jsengine/tokenizer/__init__.py
trunk/tests/warnings/useless_comparison.js
Modified: trunk/javascriptlint/warnings.py
===================================================================
--- trunk/javascriptlint/warnings.py 2013-09-28 05:00:30 UTC (rev 315)
+++ trunk/javascriptlint/warnings.py 2013-09-28 19:39:16 UTC (rev 316)
@@ -110,6 +110,7 @@
'syntax_error': 'syntax error',
'expected_tok': 'expected token: {token}',
'unexpected_char': 'unexpected character: {char}',
+ 'unexpected_eof': 'unexpected end of file',
}
def format_error(errname, **errargs):
Modified: trunk/jsengine/__init__.py
===================================================================
--- trunk/jsengine/__init__.py 2013-09-28 05:00:30 UTC (rev 315)
+++ trunk/jsengine/__init__.py 2013-09-28 19:39:16 UTC (rev 316)
@@ -1,7 +1,7 @@
# vim: sw=4 ts=4 et
_MESSAGES = (
- 'eof',
+ 'unexpected_eof',
'semi_before_stmnt',
'syntax_error',
'unterminated_comment',
Modified: trunk/jsengine/parser/__init__.py
===================================================================
--- trunk/jsengine/parser/__init__.py 2013-09-28 05:00:30 UTC (rev 315)
+++ trunk/jsengine/parser/__init__.py 2013-09-28 19:39:16 UTC (rev 316)
@@ -781,7 +781,7 @@
elif x.tok == tok.TRY:
return _try_statement(t)
elif x.tok == tok.EOF:
- raise JSSyntaxError(x.startpos, 'eof')
+ raise JSSyntaxError(x.startpos, 'unexpected_eof')
elif x.tok == tok.FUNCTION:
return _function_declaration(t, op.CLOSURE) #TODO: warn, since this is not reliable
@@ -844,7 +844,7 @@
try:
parsestring(script)
except JSSyntaxError as error:
- return error.msg not in ('eof', 'unterminated_comment')
+ return error.msg not in ('unexpected_eof', 'unterminated_comment')
return True
class TestParser(unittest.TestCase):
Modified: trunk/jsengine/tokenizer/__init__.py
===================================================================
--- trunk/jsengine/tokenizer/__init__.py 2013-09-28 05:00:30 UTC (rev 315)
+++ trunk/jsengine/tokenizer/__init__.py 2013-09-28 19:39:16 UTC (rev 316)
@@ -176,7 +176,7 @@
if self._pos < len(self._content):
self._pos += 1
return self._content[self._pos - 1]
- raise JSSyntaxError(self.getpos(-1), 'eof')
+ raise JSSyntaxError(self.getpos(-1), 'unexpected_eof')
def readif(self, len_, seq):
s = self.peekif(len_, seq)
Modified: trunk/tests/warnings/useless_comparison.js
===================================================================
--- trunk/tests/warnings/useless_comparison.js 2013-09-28 05:00:30 UTC (rev 315)
+++ trunk/tests/warnings/useless_comparison.js 2013-09-28 19:39:16 UTC (rev 316)
@@ -59,5 +59,5 @@
if (i == 3 == i) /*warning:useless_comparison*/
return;
if (i == 3 == j == 3) /*warning:useless_comparison*/
- return;}
+ return;
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mat...@us...> - 2013-09-30 20:54:01
|
Revision: 317
http://sourceforge.net/p/javascriptlint/code/317
Author: matthiasmiller
Date: 2013-09-30 20:53:58 +0000 (Mon, 30 Sep 2013)
Log Message:
-----------
Fix number parsing.
Modified Paths:
--------------
trunk/jsengine/structs.py
trunk/jsengine/tokenizer/__init__.py
trunk/tests/warnings/useless_comparison.js
Modified: trunk/jsengine/structs.py
===================================================================
--- trunk/jsengine/structs.py 2013-09-28 19:39:16 UTC (rev 316)
+++ trunk/jsengine/structs.py 2013-09-30 20:53:58 UTC (rev 317)
@@ -125,7 +125,12 @@
else:
assert fn_args is None
if self.kind == kind.NUMBER:
- self.dval = float(self.atom)
+ if self.atom.lower().startswith('0x'):
+ self.dval = int(self.atom, 16)
+ elif self.atom.startswith('0') and self.atom.isdigit():
+ self.dval = int(self.atom, 8)
+ else:
+ self.dval = float(self.atom)
def start_pos(self):
return self.startpos
Modified: trunk/jsengine/tokenizer/__init__.py
===================================================================
--- trunk/jsengine/tokenizer/__init__.py 2013-09-28 19:39:16 UTC (rev 316)
+++ trunk/jsengine/tokenizer/__init__.py 2013-09-30 20:53:58 UTC (rev 317)
@@ -378,27 +378,32 @@
s = c # TODO
stream.watch_reads()
if c == '0' and stream.readif(1, 'xX'):
+ # Hex
while stream.readif(1, _HEX_DIGITS):
pass
- return Token(tok.NUMBER, atom=stream.get_watched_reads())
-
- if c != '.':
+ elif c == '0' and stream.readif(1, _DIGITS):
+ # Octal
while stream.readif(1, _DIGITS):
pass
- stream.readif(1, '.')
+ else:
+ # Decimal
+ if c != '.':
+ while stream.readif(1, _DIGITS):
+ pass
+ stream.readif(1, '.')
- while stream.readif(1, _DIGITS):
- pass
-
- if stream.readif(1, 'eE'):
- stream.readif(1, '+-')
- stream.require(_DIGITS)
while stream.readif(1, _DIGITS):
pass
- if stream.peekchr(_IDENT):
- return Token(tok.ERROR)
+ if stream.readif(1, 'eE'):
+ stream.readif(1, '+-')
+ stream.require(_DIGITS)
+ while stream.readif(1, _DIGITS):
+ pass
+ if stream.peekchr(_IDENT):
+ return Token(tok.ERROR)
+
atom = s + stream.get_watched_reads()
return Token(tok.NUMBER, atom=atom)
Modified: trunk/tests/warnings/useless_comparison.js
===================================================================
--- trunk/tests/warnings/useless_comparison.js 2013-09-28 19:39:16 UTC (rev 316)
+++ trunk/tests/warnings/useless_comparison.js 2013-09-30 20:53:58 UTC (rev 317)
@@ -60,4 +60,10 @@
return;
if (i == 3 == j == 3) /*warning:useless_comparison*/
return;
+
+ // Test bases
+ if (010 == 8) /*warning:useless_comparison*/ /*warning:octal_number*/
+ return;
+ if (0xA == 10) /*warning:useless_comparison*/
+ return;
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mat...@us...> - 2013-09-30 20:59:58
|
Revision: 318
http://sourceforge.net/p/javascriptlint/code/318
Author: matthiasmiller
Date: 2013-09-30 20:59:56 +0000 (Mon, 30 Sep 2013)
Log Message:
-----------
Fix case preservation in control comments.
Modified Paths:
--------------
trunk/javascriptlint/lint.py
trunk/tests/warnings/unreferenced_identifier.js
Modified: trunk/javascriptlint/lint.py
===================================================================
--- trunk/javascriptlint/lint.py 2013-09-30 20:53:58 UTC (rev 317)
+++ trunk/javascriptlint/lint.py 2013-09-30 20:59:56 UTC (rev 318)
@@ -48,8 +48,8 @@
def _parse_control_comment(comment):
""" Returns None or (keyword, parms) """
- comment_atom = comment.atom.lower().strip()
- if comment_atom.startswith('jsl:'):
+ comment_atom = comment.atom.strip()
+ if comment_atom.lower().startswith('jsl:'):
control_comment = comment_atom[4:]
elif comment_atom.startswith('@') and comment_atom.endswith('@'):
control_comment = comment_atom[1:-1]
@@ -70,8 +70,8 @@
)
for keyword in keywords:
# The keyword must either match or be separated by a space.
- if control_comment == keyword or \
- (control_comment.startswith(keyword) and \
+ if control_comment.lower() == keyword or \
+ (control_comment.lower().startswith(keyword) and \
control_comment[len(keyword)].isspace()):
parms = control_comment[len(keyword):].strip()
return (comment, keyword, parms.strip())
Modified: trunk/tests/warnings/unreferenced_identifier.js
===================================================================
--- trunk/tests/warnings/unreferenced_identifier.js 2013-09-30 20:53:58 UTC (rev 317)
+++ trunk/tests/warnings/unreferenced_identifier.js 2013-09-30 20:59:56 UTC (rev 318)
@@ -98,5 +98,9 @@
}
}
+ function test_unused_camel_case(CamelCaseParm) { /*warning:unreferenced_function*/
+ /*jsl:unused CamelCaseParm*/
+ }
+
return get_callback(42);
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mat...@us...> - 2013-09-30 21:03:26
|
Revision: 319
http://sourceforge.net/p/javascriptlint/code/319
Author: matthiasmiller
Date: 2013-09-30 21:03:23 +0000 (Mon, 30 Sep 2013)
Log Message:
-----------
Allow chained assigns.
Modified Paths:
--------------
trunk/javascriptlint/warnings.py
trunk/tests/warnings/equal_as_assign.js
Modified: trunk/javascriptlint/warnings.py
===================================================================
--- trunk/javascriptlint/warnings.py 2013-09-30 20:59:56 UTC (rev 318)
+++ trunk/javascriptlint/warnings.py 2013-09-30 21:03:23 UTC (rev 319)
@@ -324,7 +324,8 @@
@lookfor(tok.ASSIGN)
def equal_as_assign(node):
- if not node.parent.kind in (tok.SEMI, tok.RESERVED, tok.RP, tok.COMMA):
+ if not node.parent.kind in (tok.SEMI, tok.RESERVED, tok.RP, tok.COMMA,
+ tok.ASSIGN):
raise LintWarning, node
@lookfor(tok.IF)
Modified: trunk/tests/warnings/equal_as_assign.js
===================================================================
--- trunk/tests/warnings/equal_as_assign.js 2013-09-30 20:59:56 UTC (rev 318)
+++ trunk/tests/warnings/equal_as_assign.js 2013-09-30 21:03:23 UTC (rev 319)
@@ -4,4 +4,7 @@
while (a = b) { /*warning:equal_as_assign*/
a++;
}
+
+ var c;
+ a = b = c;
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mat...@us...> - 2013-09-30 21:11:48
|
Revision: 320
http://sourceforge.net/p/javascriptlint/code/320
Author: matthiasmiller
Date: 2013-09-30 21:11:45 +0000 (Mon, 30 Sep 2013)
Log Message:
-----------
Allow chained assignments in VAR statements.
Modified Paths:
--------------
trunk/javascriptlint/warnings.py
trunk/tests/warnings/equal_as_assign.js
Modified: trunk/javascriptlint/warnings.py
===================================================================
--- trunk/javascriptlint/warnings.py 2013-09-30 21:03:23 UTC (rev 319)
+++ trunk/javascriptlint/warnings.py 2013-09-30 21:11:45 UTC (rev 320)
@@ -324,6 +324,10 @@
@lookfor(tok.ASSIGN)
def equal_as_assign(node):
+ # Allow in VAR statements.
+ if node.parent.parent and node.parent.parent.kind == tok.VAR:
+ return
+
if not node.parent.kind in (tok.SEMI, tok.RESERVED, tok.RP, tok.COMMA,
tok.ASSIGN):
raise LintWarning, node
Modified: trunk/tests/warnings/equal_as_assign.js
===================================================================
--- trunk/tests/warnings/equal_as_assign.js 2013-09-30 21:03:23 UTC (rev 319)
+++ trunk/tests/warnings/equal_as_assign.js 2013-09-30 21:11:45 UTC (rev 320)
@@ -7,4 +7,7 @@
var c;
a = b = c;
+
+ var x, y, z;
+ var w = x = y = z;
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mat...@us...> - 2013-09-30 21:19:29
|
Revision: 321
http://sourceforge.net/p/javascriptlint/code/321
Author: matthiasmiller
Date: 2013-09-30 21:19:27 +0000 (Mon, 30 Sep 2013)
Log Message:
-----------
Don't warning against increment/decrement assignments in expressions.
Modified Paths:
--------------
trunk/javascriptlint/warnings.py
trunk/tests/warnings/equal_as_assign.js
Modified: trunk/javascriptlint/warnings.py
===================================================================
--- trunk/javascriptlint/warnings.py 2013-09-30 21:11:45 UTC (rev 320)
+++ trunk/javascriptlint/warnings.py 2013-09-30 21:19:27 UTC (rev 321)
@@ -322,7 +322,7 @@
if kid.kind == tok.LP:
raise LintWarning, node
-@lookfor(tok.ASSIGN)
+@lookfor((tok.ASSIGN, None))
def equal_as_assign(node):
# Allow in VAR statements.
if node.parent.parent and node.parent.parent.kind == tok.VAR:
Modified: trunk/tests/warnings/equal_as_assign.js
===================================================================
--- trunk/tests/warnings/equal_as_assign.js 2013-09-30 21:11:45 UTC (rev 320)
+++ trunk/tests/warnings/equal_as_assign.js 2013-09-30 21:19:27 UTC (rev 321)
@@ -4,6 +4,9 @@
while (a = b) { /*warning:equal_as_assign*/
a++;
}
+ while (a -= b) {
+ a--;
+ }
var c;
a = b = c;
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mat...@us...> - 2013-09-30 21:54:35
|
Revision: 322
http://sourceforge.net/p/javascriptlint/code/322
Author: matthiasmiller
Date: 2013-09-30 21:54:32 +0000 (Mon, 30 Sep 2013)
Log Message:
-----------
Fix single-line returns without semicolons.
Modified Paths:
--------------
trunk/jsengine/parser/__init__.py
Added Paths:
-----------
trunk/tests/bugs/one_line_return.js
Modified: trunk/jsengine/parser/__init__.py
===================================================================
--- trunk/jsengine/parser/__init__.py 2013-09-30 21:19:27 UTC (rev 321)
+++ trunk/jsengine/parser/__init__.py 2013-09-30 21:54:32 UTC (rev 322)
@@ -638,7 +638,7 @@
endtoken = t.expect(tok.RETURN)
startpos = endtoken.startpos
- if t.peek_sameline().tok not in (tok.EOF, tok.EOL, tok.SEMI):
+ if t.peek_sameline().tok not in (tok.EOF, tok.EOL, tok.SEMI, tok.RBRACE):
expr = _expression(t, True)
endtoken = expr
else:
Added: trunk/tests/bugs/one_line_return.js
===================================================================
--- trunk/tests/bugs/one_line_return.js (rev 0)
+++ trunk/tests/bugs/one_line_return.js 2013-09-30 21:54:32 UTC (rev 322)
@@ -0,0 +1,2 @@
+function one_line_return() { return } /*warning:missing_semicolon*/
+
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mat...@us...> - 2013-09-30 23:16:40
|
Revision: 323
http://sourceforge.net/p/javascriptlint/code/323
Author: matthiasmiller
Date: 2013-09-30 23:16:37 +0000 (Mon, 30 Sep 2013)
Log Message:
-----------
Function expressions should not declare a variable.
Modified Paths:
--------------
trunk/javascriptlint/lint.py
trunk/jsengine/parser/__init__.py
trunk/tests/control_comments/option_explicit.js
Modified: trunk/javascriptlint/lint.py
===================================================================
--- trunk/javascriptlint/lint.py 2013-09-30 21:54:32 UTC (rev 322)
+++ trunk/javascriptlint/lint.py 2013-09-30 23:16:37 UTC (rev 323)
@@ -609,7 +609,7 @@
@visitation.visit('push', tok.FUNCTION)
def _push_func(self, node):
- if node.fn_name:
+ if node.opcode != op.CLOSURE and node.fn_name:
_warn_or_declare(scopes[-1], node.fn_name, 'function', node, report)
self._push_scope(node)
for var_name in node.fn_args:
Modified: trunk/jsengine/parser/__init__.py
===================================================================
--- trunk/jsengine/parser/__init__.py 2013-09-30 21:54:32 UTC (rev 322)
+++ trunk/jsengine/parser/__init__.py 2013-09-30 23:16:37 UTC (rev 323)
@@ -162,10 +162,8 @@
fn_body_endpos = t.expect(tok.RBRACE).endpos
fn_body = ParseNode(kind.LC, None, fn_body_startpos,
fn_body_endpos, None, kids)
- return ParseNode(kind.FUNCTION,
- op.ANONFUNOBJ if fn_name is None else op.NAMEDFUNOBJ,
- startpos, fn_body.endpos,
- fn_name, [fn_body], fn_args=fn_args)
+ return ParseNode(kind.FUNCTION, opcode, startpos, fn_body.endpos,
+ fn_name, [fn_body], fn_args=fn_args)
def _argument_list(t):
args = []
Modified: trunk/tests/control_comments/option_explicit.js
===================================================================
--- trunk/tests/control_comments/option_explicit.js 2013-09-30 21:54:32 UTC (rev 322)
+++ trunk/tests/control_comments/option_explicit.js 2013-09-30 23:16:37 UTC (rev 323)
@@ -60,5 +60,12 @@
/* illegal */
y(); /*warning:undeclared_identifier*/
+ // This should be undeclared because this is an expression,
+ // not a declaration.
+ (function func_expr() { /*warning:want_assign_or_call*/
+ return 10;
+ });
+ j = func_expr();
+
return "";
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mat...@us...> - 2013-10-01 17:07:15
|
Revision: 324
http://sourceforge.net/p/javascriptlint/code/324
Author: matthiasmiller
Date: 2013-10-01 17:07:11 +0000 (Tue, 01 Oct 2013)
Log Message:
-----------
Correctly handle top-level function declarations.
Modified Paths:
--------------
trunk/javascriptlint/lint.py
trunk/tests/control_comments/option_explicit.js
trunk/tests/warnings/redeclared_var.js
trunk/tests/warnings/unreferenced_identifier.js
Modified: trunk/javascriptlint/lint.py
===================================================================
--- trunk/javascriptlint/lint.py 2013-09-30 23:16:37 UTC (rev 323)
+++ trunk/javascriptlint/lint.py 2013-10-01 17:07:11 UTC (rev 324)
@@ -609,7 +609,7 @@
@visitation.visit('push', tok.FUNCTION)
def _push_func(self, node):
- if node.opcode != op.CLOSURE and node.fn_name:
+ if node.opcode in (None, op.CLOSURE) and node.fn_name:
_warn_or_declare(scopes[-1], node.fn_name, 'function', node, report)
self._push_scope(node)
for var_name in node.fn_args:
Modified: trunk/tests/control_comments/option_explicit.js
===================================================================
--- trunk/tests/control_comments/option_explicit.js 2013-09-30 23:16:37 UTC (rev 323)
+++ trunk/tests/control_comments/option_explicit.js 2013-10-01 17:07:11 UTC (rev 324)
@@ -65,7 +65,10 @@
(function func_expr() { /*warning:want_assign_or_call*/
return 10;
});
- j = func_expr();
+ j = func_expr(); /*warning:undeclared_identifier*/
return "";
}
+
+// Ensure that we can reference top-level functions.
+option_explicit(null);
Modified: trunk/tests/warnings/redeclared_var.js
===================================================================
--- trunk/tests/warnings/redeclared_var.js 2013-09-30 23:16:37 UTC (rev 323)
+++ trunk/tests/warnings/redeclared_var.js 2013-10-01 17:07:11 UTC (rev 324)
@@ -7,4 +7,9 @@
return;
}
var myFunction; /*warning:redeclared_var*/
+
+ // myFunction isn't a redeclaration, since function names in function
+ // expressions don't matter.
+ var tmp = function myFunction(){};
+ /*jsl:unused tmp*/
}
Modified: trunk/tests/warnings/unreferenced_identifier.js
===================================================================
--- trunk/tests/warnings/unreferenced_identifier.js 2013-09-30 23:16:37 UTC (rev 323)
+++ trunk/tests/warnings/unreferenced_identifier.js 2013-10-01 17:07:11 UTC (rev 324)
@@ -74,8 +74,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_function*/
+ /* Test named functions as references.
+ * (The name is ignored since it's a function expression.)
+ */
+ var fn = function ref_func() { return 42; };
fn();
/* Test nested scopes. */
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mat...@us...> - 2013-10-01 17:12:24
|
Revision: 325
http://sourceforge.net/p/javascriptlint/code/325
Author: matthiasmiller
Date: 2013-10-01 17:12:20 +0000 (Tue, 01 Oct 2013)
Log Message:
-----------
First cut at warnings to validate function expression names (disabled by default)
Modified Paths:
--------------
trunk/javascriptlint/conf.py
trunk/javascriptlint/warnings.py
trunk/tests/control_comments/option_explicit.js
trunk/tests/warnings/want_assign_or_call.js
Added Paths:
-----------
trunk/tests/warnings/function_name_mismatch.js
trunk/tests/warnings/function_name_missing.js
trunk/tests/warnings/misplaced_function.js
Modified: trunk/javascriptlint/conf.py
===================================================================
--- trunk/javascriptlint/conf.py 2013-10-01 17:07:11 UTC (rev 324)
+++ trunk/javascriptlint/conf.py 2013-10-01 17:12:20 UTC (rev 325)
@@ -6,12 +6,18 @@
import util
import warnings
+_DISABLED_WARNINGS = (
+ 'block_without_braces',
+ 'function_name_missing',
+ 'function_name_mismatch',
+)
+
def _getwarningsconf():
lines = []
for name in sorted(warnings.warnings.keys()):
message = warnings.warnings[name]
sign = '+'
- if name == 'block_without_braces':
+ if name in _DISABLED_WARNINGS:
sign = '-'
assert len(name) < 29
lines.append(sign + name.ljust(29) + '# ' + message)
@@ -183,7 +189,8 @@
}
for name in warnings.warnings:
self._settings[name] = BooleanSetting(True)
- self.loadline('-block_without_braces')
+ for warning in _DISABLED_WARNINGS:
+ self.loadline('-%s' % warning)
def loadfile(self, path):
path = os.path.abspath(path)
Modified: trunk/javascriptlint/warnings.py
===================================================================
--- trunk/javascriptlint/warnings.py 2013-10-01 17:07:11 UTC (rev 324)
+++ trunk/javascriptlint/warnings.py 2013-10-01 17:12:20 UTC (rev 325)
@@ -102,6 +102,9 @@
'unsupported_version': 'JavaScript {version} is not supported',
'incorrect_version': 'Expected /*jsl:content-type*/ control comment. The script was parsed with the wrong version.',
'for_in_missing_identifier': 'for..in should have identifier on left side',
+ 'misplaced_function': 'unconventional use of function expression',
+ 'function_name_missing': 'anonymous function should be named to match property name {name}',
+ 'function_name_mismatch': 'function name {fn_name} does not match property name {prop_name}',
}
errors = {
@@ -604,6 +607,87 @@
if not left.kind in (tok.VAR, tok.NAME):
raise LintWarning, left
+@lookfor(tok.FUNCTION)
+def misplaced_function(node):
+ # Ignore function statements.
+ if node.opcode in (None, op.CLOSURE):
+ return
+
+ # Ignore parens.
+ parent = node.parent
+ while parent.kind == tok.RP:
+ parent = parent.parent
+
+ # Allow x = x || ...
+ if parent.kind == tok.OR and len(parent.kids) == 2 and \
+ node is parent.kids[-1]:
+ parent = parent.parent
+
+ if parent.kind == tok.NAME and parent.opcode == op.SETNAME:
+ return # Allow in var statements
+ if parent.kind == tok.ASSIGN and parent.opcode == op.NOP:
+ return # Allow in assigns
+ if parent.kind == tok.COLON and parent.parent.kind == tok.RC:
+ return # Allow in object literals
+ if parent.kind == tok.LP and parent.opcode in (op.CALL, op.SETCALL):
+ return # Allow in parameters
+ if parent.kind == tok.RETURN:
+ return # Allow for return values
+ if parent.kind == tok.NEW:
+ return # Allow as constructors
+ raise LintWarning, node
+
+def _get_expected_function_name(node):
+ # Ignore function statements.
+ if node.opcode in (None, op.CLOSURE):
+ return
+
+ # Ignore parens.
+ parent = node.parent
+ while parent.kind == tok.RP:
+ parent = parent.parent
+
+ # Allow x = x || ...
+ if parent.kind == tok.OR and len(parent.kids) == 2 and \
+ node is parent.kids[-1]:
+ parent = parent.parent
+
+ # Var assignment.
+ if parent.kind == tok.NAME and parent.opcode == op.SETNAME:
+ return parent.atom
+
+ # Assignment.
+ if parent.kind == tok.ASSIGN and parent.opcode == op.NOP:
+ if parent.kids[0].kind == tok.NAME and \
+ parent.kids[0].opcode == op.SETNAME:
+ return parent.kids[0].atom
+ return '<error>'
+
+ # Object literal.
+ if parent.kind == tok.COLON and parent.parent.kind == tok.RC:
+ return parent.kids[0].atom
+
+@lookfor(tok.FUNCTION)
+def function_name_missing(node):
+ if node.fn_name:
+ return
+
+ expected_name = _get_expected_function_name(node)
+ if not expected_name is None:
+ raise LintWarning(node, name=expected_name)
+
+@lookfor(tok.FUNCTION)
+def function_name_mismatch(node):
+ if not node.fn_name:
+ return
+
+ expected_name = _get_expected_function_name(node)
+ if expected_name is None:
+ return
+
+ if expected_name != node.fn_name:
+ raise LintWarning(node, fn_name=node.fn_name, prop_name=expected_name)
+
@lookfor()
def mismatch_ctrl_comments(node):
pass
Modified: trunk/tests/control_comments/option_explicit.js
===================================================================
--- trunk/tests/control_comments/option_explicit.js 2013-10-01 17:07:11 UTC (rev 324)
+++ trunk/tests/control_comments/option_explicit.js 2013-10-01 17:12:20 UTC (rev 325)
@@ -62,7 +62,7 @@
// This should be undeclared because this is an expression,
// not a declaration.
- (function func_expr() { /*warning:want_assign_or_call*/
+ (function func_expr() { /*warning:misplaced_function*/ /*warning:want_assign_or_call*/
return 10;
});
j = func_expr(); /*warning:undeclared_identifier*/
Added: trunk/tests/warnings/function_name_mismatch.js
===================================================================
--- trunk/tests/warnings/function_name_mismatch.js (rev 0)
+++ trunk/tests/warnings/function_name_mismatch.js 2013-10-01 17:12:20 UTC (rev 325)
@@ -0,0 +1,36 @@
+/*conf:+function_name_mismatch*/
+function function_name_mismatch() {
+ var f = function bogus() { /*warning:function_name_mismatch*/
+ };
+ var g = function g() {
+ };
+
+ f = new function bogus() {
+ };
+ f = new function() {
+ };
+
+ f = (function() {
+ return 10;
+ })();
+
+ var o = {
+ f: function bogus() { /*warning:function_name_mismatch*/
+ return null;
+ }
+ };
+ o.a.b = {
+ f: function bogus() { /*warning:function_name_mismatch*/
+ return null;
+ }
+ };
+ o.a.b = o.a.b || function bogus() { return 10; }; /*warning:function_name_mismatch*/
+
+ function closure(a) {
+ return function() { return a; };
+ }
+
+ function x() {
+ }
+}
+
Added: trunk/tests/warnings/function_name_missing.js
===================================================================
--- trunk/tests/warnings/function_name_missing.js (rev 0)
+++ trunk/tests/warnings/function_name_missing.js 2013-10-01 17:12:20 UTC (rev 325)
@@ -0,0 +1,30 @@
+/*conf:+function_name_missing*/
+function function_name_missing() {
+ var f = function() { /*warning:function_name_missing*/
+ };
+ f = new function() {
+ };
+ f = (function() {
+ return 10;
+ })();
+
+ var o = {
+ f: function() { /*warning:function_name_missing*/
+ return null;
+ }
+ };
+ o.a.b = {
+ f: function() { /*warning:function_name_missing*/
+ return null;
+ }
+ };
+ o.a.b = o.a.b || function() { return 10; }; /*warning:function_name_missing*/
+
+ function closure(a) {
+ return function() { return a; };
+ }
+
+ function x() {
+ }
+}
+
Added: trunk/tests/warnings/misplaced_function.js
===================================================================
--- trunk/tests/warnings/misplaced_function.js (rev 0)
+++ trunk/tests/warnings/misplaced_function.js 2013-10-01 17:12:20 UTC (rev 325)
@@ -0,0 +1,33 @@
+/*conf:-want_assign_or_call*/
+function misplaced_functions() {
+ var f = function() {
+ };
+ f = new function() {
+ };
+ f = (function() {
+ return 10;
+ })();
+
+ var o = {
+ f: function() {
+ return null;
+ }
+ };
+ o.a.b = {
+ f: function() {
+ return null;
+ }
+ };
+ o.a.b = o.a.b || function() { return 10; };
+ o.a.b = o.a.c || function() { return 10; }; /*TODO*/
+
+ function closure(a) {
+ return function() { return a; };
+ }
+
+ function x() {
+ }
+
+ function() {}; /*warning:misplaced_function*/
+}
+
Modified: trunk/tests/warnings/want_assign_or_call.js
===================================================================
--- trunk/tests/warnings/want_assign_or_call.js 2013-10-01 17:07:11 UTC (rev 324)
+++ trunk/tests/warnings/want_assign_or_call.js 2013-10-01 17:12:20 UTC (rev 325)
@@ -14,7 +14,7 @@
function test() {
}
- function() { /*warning:want_assign_or_call*/
+ function() { /*warning:want_assign_or_call*/ /*warning:misplaced_function*/
return 42;
};
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mat...@us...> - 2013-10-02 23:18:33
|
Revision: 327
http://sourceforge.net/p/javascriptlint/code/327
Author: matthiasmiller
Date: 2013-10-02 23:18:30 +0000 (Wed, 02 Oct 2013)
Log Message:
-----------
pylint: fix raise syntax
Modified Paths:
--------------
trunk/javascriptlint/conf.py
trunk/javascriptlint/visitation.py
trunk/javascriptlint/warnings.py
trunk/setup.py
trunk/test.py
trunk/www.py
Modified: trunk/javascriptlint/conf.py
===================================================================
--- trunk/javascriptlint/conf.py 2013-10-02 23:16:54 UTC (rev 326)
+++ trunk/javascriptlint/conf.py 2013-10-02 23:18:30 UTC (rev 327)
@@ -119,7 +119,7 @@
wants_parm = False
value = None
def load(self, enabled):
- raise ConfError, 'This setting is deprecated.'
+ raise ConfError('This setting is deprecated.')
class BooleanSetting(Setting):
wants_parm = False
@@ -134,7 +134,7 @@
self.value = default
def load(self, enabled, parm):
if not enabled:
- raise ConfError, 'Expected +.'
+ raise ConfError('Expected +.')
self.value = parm
class DeclareSetting(Setting):
@@ -143,7 +143,7 @@
self.value = []
def load(self, enabled, parm):
if not enabled:
- raise ConfError, 'Expected +.'
+ raise ConfError('Expected +.')
self.value.append(parm)
class ProcessSetting(Setting):
@@ -162,11 +162,11 @@
value = util.JSVersion.default()
def load(self, enabled, parm):
if not enabled:
- raise ConfError, 'Expected +.'
+ raise ConfError('Expected +.')
self.value = util.JSVersion.fromtype(parm)
if not self.value:
- raise ConfError, 'Invalid JavaScript version: %s' % parm
+ raise ConfError('Invalid JavaScript version: %s' % parm)
class Conf:
def __init__(self):
@@ -227,7 +227,7 @@
elif line.startswith('-'):
enabled = False
else:
- raise ConfError, 'Expected + or -.'
+ raise ConfError('Expected + or -.')
line = line[1:]
# Parse the key/parms
@@ -242,7 +242,7 @@
if setting.wants_parm:
args['parm'] = parm
elif parm:
- raise ConfError, 'The %s setting does not expect a parameter.' % name
+ raise ConfError('The %s setting does not expect a parameter.' % name)
if setting.wants_dir:
args['dir'] = dir
setting.load(**args)
Modified: trunk/javascriptlint/visitation.py
===================================================================
--- trunk/javascriptlint/visitation.py 2013-10-02 23:16:54 UTC (rev 326)
+++ trunk/javascriptlint/visitation.py 2013-10-02 23:18:30 UTC (rev 327)
@@ -27,9 +27,9 @@
# Intantiate an instance of each class
for klass in klasses:
if klass.__name__.lower() != klass.__name__:
- raise ValueError, 'class names must be lowercase'
+ raise ValueError('class names must be lowercase')
if not klass.__doc__:
- raise ValueError, 'missing docstring on class %s' % klass.__name__
+ raise ValueError('missing docstring on class %s' % klass.__name__)
# Look for functions with the "_visit_nodes" property.
visitor = klass()
Modified: trunk/javascriptlint/warnings.py
===================================================================
--- trunk/javascriptlint/warnings.py 2013-10-02 23:16:54 UTC (rev 326)
+++ trunk/javascriptlint/warnings.py 2013-10-02 23:18:30 UTC (rev 327)
@@ -12,7 +12,7 @@
@lookfor(tok.NODEKIND, (tok.NODEKIND, op.OPCODE))
def warning_name(node):
if questionable:
- raise LintWarning, node
+ raise LintWarning(node)
"""
import itertools
import re
@@ -125,7 +125,7 @@
try:
errdesc = re.sub(r"{(\w+)}", lambda match: errargs[match.group(1)], errdesc)
except (TypeError, KeyError):
- raise KeyError, 'Invalid keyword in error: ' + errdesc
+ raise KeyError('Invalid keyword in error: ' + errdesc)
return errdesc
_visitors = []
@@ -253,17 +253,17 @@
def comparison_type_conv(node):
for kid in node.kids:
if kid.kind == tok.PRIMARY and kid.opcode in (op.NULL, op.TRUE, op.FALSE):
- raise LintWarning, kid
+ raise LintWarning(kid)
if kid.kind == tok.NUMBER and not kid.dval:
- raise LintWarning, kid
+ raise LintWarning(kid)
if kid.kind == tok.STRING and not kid.atom:
- raise LintWarning, kid
+ raise LintWarning(kid)
@lookfor(tok.DEFAULT)
def default_not_at_end(node):
siblings = node.parent.kids
if node.node_index != len(siblings)-1:
- raise LintWarning, siblings[node.node_index+1]
+ raise LintWarning(siblings[node.node_index+1])
@lookfor(tok.CASE)
def duplicate_case_in_switch(node):
@@ -276,7 +276,7 @@
if sibling.kind == tok.CASE:
sibling_value = sibling.kids[0]
if node_value.is_equivalent(sibling_value, True):
- raise LintWarning, node
+ raise LintWarning(node)
@lookfor(tok.SWITCH)
def missing_default_case(node):
@@ -284,21 +284,21 @@
for case in cases.kids:
if case.kind == tok.DEFAULT:
return
- raise LintWarning, node
+ raise LintWarning(node)
@lookfor(tok.WITH)
def with_statement(node):
- raise LintWarning, node
+ raise LintWarning(node)
@lookfor(tok.EQOP,tok.RELOP)
def useless_comparison(node):
for lvalue, rvalue in itertools.combinations(node.kids, 2):
if lvalue.is_equivalent(rvalue):
- raise LintWarning, node
+ raise LintWarning(node)
@lookfor((tok.COLON, op.NAME))
def use_of_label(node):
- raise LintWarning, node
+ raise LintWarning(node)
@lookfor((tok.OBJECT, op.REGEXP))
def misplaced_regex(node):
@@ -314,7 +314,7 @@
return # Allow in /re/.property
if node.parent.kind == tok.RETURN:
return # Allow for return values
- raise LintWarning, node
+ raise LintWarning(node)
@lookfor(tok.ASSIGN)
def assign_to_function_call(node):
@@ -323,7 +323,7 @@
while kid.kind == tok.RP:
kid, = kid.kids
if kid.kind == tok.LP:
- raise LintWarning, node
+ raise LintWarning(node)
@lookfor((tok.ASSIGN, None))
def equal_as_assign(node):
@@ -333,7 +333,7 @@
if not node.parent.kind in (tok.SEMI, tok.RESERVED, tok.RP, tok.COMMA,
tok.ASSIGN):
- raise LintWarning, node
+ raise LintWarning(node)
@lookfor(tok.IF)
def ambiguous_else_stmt(node):
@@ -349,13 +349,13 @@
return
# Else is only ambiguous in the first branch of an if statement.
if tmp.parent.kind == tok.IF and tmp.node_index == 1:
- raise LintWarning, else_
+ raise LintWarning(else_)
tmp = tmp.parent
@lookfor(tok.IF, tok.WHILE, tok.DO, tok.FOR, tok.WITH)
def block_without_braces(node):
if node.kids[1].kind != tok.LC:
- raise LintWarning, node.kids[1]
+ raise LintWarning(node.kids[1])
_block_nodes = (tok.IF, tok.WHILE, tok.DO, tok.FOR, tok.WITH)
@lookfor(*_block_nodes)
@@ -368,7 +368,7 @@
# was inside a block statement without clarifying curlies.
# (Otherwise, the node type would be tok.LC.)
if node.parent.kind in _block_nodes:
- raise LintWarning, node
+ raise LintWarning(node)
@lookfor(tok.INC, tok.DEC)
def inc_dec_within_stmt(node):
@@ -384,7 +384,7 @@
tmp.parent.parent.kind == tok.FOR:
return
- raise LintWarning, node
+ raise LintWarning(node)
@lookfor(tok.COMMA)
def comma_separated_stmts(node):
@@ -394,12 +394,12 @@
# This is an array
if node.parent.kind == tok.RB:
return
- raise LintWarning, node
+ raise LintWarning(node)
@lookfor(tok.SEMI)
def empty_statement(node):
if not node.kids[0]:
- raise LintWarning, node
+ raise LintWarning(node)
@lookfor(tok.LC)
def empty_statement_(node):
if node.kids:
@@ -410,7 +410,7 @@
# Some empty blocks are meaningful.
if node.parent.kind in (tok.CATCH, tok.CASE, tok.DEFAULT, tok.SWITCH, tok.FUNCTION):
return
- raise LintWarning, node
+ raise LintWarning(node)
@lookfor(tok.CASE, tok.DEFAULT)
def missing_break(node):
@@ -424,7 +424,7 @@
return
if None in _get_exit_points(case_contents):
# Show the warning on the *next* node.
- raise LintWarning, node.parent.kids[node.node_index+1]
+ raise LintWarning(node.parent.kids[node.node_index+1])
@lookfor(tok.CASE, tok.DEFAULT)
def missing_break_for_last_case(node):
@@ -433,16 +433,16 @@
case_contents = node.kids[1]
assert case_contents.kind == tok.LC
if None in _get_exit_points(case_contents):
- raise LintWarning, node
+ raise LintWarning(node)
@lookfor(tok.INC)
def multiple_plus_minus(node):
if node.node_index == 0 and node.parent.kind == tok.PLUS:
- raise LintWarning, node
+ raise LintWarning(node)
@lookfor(tok.DEC)
def multiple_plus_minus_(node):
if node.node_index == 0 and node.parent.kind == tok.MINUS:
- raise LintWarning, node
+ raise LintWarning(node)
@lookfor((tok.NAME, op.SETNAME))
def useless_assign(node):
@@ -452,7 +452,7 @@
elif node.parent.kind == tok.VAR:
value = node.kids[0]
if value and value.kind == tok.NAME and node.atom == value.atom:
- raise LintWarning, node
+ raise LintWarning(node)
@lookfor(tok.BREAK, tok.CONTINUE, tok.RETURN, tok.THROW)
def unreachable_code(node):
@@ -463,12 +463,12 @@
for variable in sibling.kids:
value, = variable.kids
if value:
- raise LintWarning, value
+ raise LintWarning(value)
elif sibling.kind == tok.FUNCTION:
# Functions are always declared.
pass
else:
- raise LintWarning, sibling
+ raise LintWarning(sibling)
@lookfor(tok.FOR)
def unreachable_code_(node):
@@ -478,73 +478,73 @@
pre, condition, post = preamble.kids
if post:
if not None in _get_exit_points(code):
- raise LintWarning, post
+ 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
+ raise LintWarning(condition)
#TODO: @lookfor(tok.IF)
def meaningless_block(node):
condition, if_, else_ = node.kids
if condition.kind == tok.PRIMARY and condition.opcode in (op.TRUE, op.FALSE, op.NULL):
- raise LintWarning, condition
+ raise LintWarning(condition)
#TODO: @lookfor(tok.WHILE)
def meaningless_blocK_(node):
condition = node.kids[0]
if condition.kind == tok.PRIMARY and condition.opcode in (op.FALSE, op.NULL):
- raise LintWarning, condition
+ raise LintWarning(condition)
@lookfor(tok.LC)
def meaningless_block__(node):
if node.parent and node.parent.kind == tok.LC:
- raise LintWarning, node
+ raise LintWarning(node)
@lookfor((tok.UNARYOP, op.VOID))
def useless_void(node):
- raise LintWarning, node
+ raise LintWarning(node)
@lookfor((tok.LP, op.CALL))
def parseint_missing_radix(node):
if node.kids[0].kind == tok.NAME and node.kids[0].atom == 'parseInt' and len(node.kids) <= 2:
- raise LintWarning, node
+ raise LintWarning(node)
@lookfor(tok.NUMBER)
def leading_decimal_point(node):
if node.atom.startswith('.'):
- raise LintWarning, node
+ raise LintWarning(node)
@lookfor(tok.NUMBER)
def trailing_decimal_point(node):
if node.parent.kind == tok.DOT:
- raise LintWarning, node
+ raise LintWarning(node)
if node.atom.endswith('.'):
- raise LintWarning, node
+ raise LintWarning(node)
_octal_regexp = re.compile('^0[0-9]')
@lookfor(tok.NUMBER)
def octal_number(node):
if _octal_regexp.match(node.atom):
- raise LintWarning, node
+ raise LintWarning(node)
@lookfor(tok.RC)
def trailing_comma(node):
if node.end_comma:
- raise LintWarning, node
+ raise LintWarning(node)
@lookfor(tok.RB)
def trailing_comma_in_array(node):
if node.end_comma:
- raise LintWarning, node
+ raise LintWarning(node)
@lookfor(tok.STRING)
def useless_quotes(node):
if node.node_index == 0 and node.parent.kind == tok.COLON:
# Only warn if the quotes could safely be removed.
if util.isidentifier(node.atom):
- raise LintWarning, node
+ raise LintWarning(node)
@lookfor(tok.SEMI)
def want_assign_or_call(node):
@@ -566,7 +566,7 @@
grandchild = child.kids[0]
if grandchild.kind == tok.FUNCTION:
return
- raise LintWarning, child
+ raise LintWarning(child)
def _check_return_value(node):
name = node.fn_name or '(anonymous function)'
@@ -605,7 +605,7 @@
assert node.kids[0].kind == tok.IN
left, right = node.kids[0].kids
if not left.kind in (tok.VAR, tok.NAME):
- raise LintWarning, left
+ raise LintWarning(left)
@lookfor(tok.FUNCTION)
def misplaced_function(node):
@@ -635,7 +635,7 @@
return # Allow for return values
if parent.kind == tok.NEW:
return # Allow as constructors
- raise LintWarning, node
+ raise LintWarning(node)
def _get_expected_function_name(node):
# Ignore function statements.
@@ -724,7 +724,7 @@
def missing_semicolon(node):
if node.no_semi:
if not _get_assigned_lambda(node):
- raise LintWarning, node
+ raise LintWarning(node)
@lookfor(*_ALL_TOKENS)
def missing_semicolon_for_lambda(node):
@@ -733,7 +733,7 @@
# statements, so use the position of the lambda instead.
lambda_ = _get_assigned_lambda(node)
if lambda_:
- raise LintWarning, lambda_
+ raise LintWarning(lambda_)
@lookfor()
def ambiguous_newline(node):
Modified: trunk/setup.py
===================================================================
--- trunk/setup.py 2013-10-02 23:16:54 UTC (rev 326)
+++ trunk/setup.py 2013-10-02 23:18:30 UTC (rev 327)
@@ -16,7 +16,7 @@
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = p.communicate()
if p.returncode != 0:
- raise _BuildError, 'Error running svnversion: %s' % stderr
+ raise _BuildError('Error running svnversion: %s' % stderr)
version = stdout.strip().rstrip('M')
return int(version)
@@ -48,7 +48,7 @@
for exe in self.console_exe_files:
ret = subprocess.call(['upx', '-9', exe])
if ret != 0:
- raise _BuildError, 'Error running upx on %s' % exe
+ raise _BuildError('Error running upx on %s' % exe)
args['cmdclass']['py2exe'] = _MyPy2Exe
args.update(
Modified: trunk/test.py
===================================================================
--- trunk/test.py 2013-10-02 23:16:54 UTC (rev 326)
+++ trunk/test.py 2013-10-02 23:18:30 UTC (rev 327)
@@ -76,7 +76,7 @@
for line, warning, errdesc in unexpected_warnings:
errors.append('\tline %i: %s/%s' % (line+1, warning, errdesc))
if errors:
- raise TestError, '\n'.join(errors)
+ raise TestError('\n'.join(errors))
def _get_test_files():
# Get a list of test files.
@@ -143,7 +143,6 @@
'R0924', # Badly implemented
'W0109', # Duplicate key %r in dictionary
'W0120', # Else clause on loop without a break statement
- 'W0121', # old-raise-syntax
'W0141', # Used builtin function %r
'W0201', # Attribute %r defined outside __init__
'W0212', # Access to a protected member %s of a client class
Modified: trunk/www.py
===================================================================
--- trunk/www.py 2013-10-02 23:16:54 UTC (rev 326)
+++ trunk/www.py 2013-10-02 23:18:30 UTC (rev 327)
@@ -53,7 +53,7 @@
if not attrvalue.startswith('/'):
targetpath = _get_path_for_url(attrvalue, self._filepath)
if not targetpath:
- raise ValueError, 'Could not resolve URL %s' % attrvalue
+ raise ValueError('Could not resolve URL %s' % attrvalue)
# Get the folder of the parent path.
parenturl = _get_relurl_for_filepath(self._filepath)
@@ -89,7 +89,7 @@
root = os.path.dirname(parentpath)
assert (root + os.sep).startswith(DOC_ROOT + os.sep)
else:
- raise ValueError, 'Tried resolving relative URL: %s' % url
+ raise ValueError('Tried resolving relative URL: %s' % url)
urls = [
url.rstrip('/') + '/index.htm',
@@ -136,11 +136,11 @@
channel = doc.createElement("channel")
rss.appendChild(channel)
if not title:
- raise ValueError, 'Missing @title= setting.'
+ raise ValueError('Missing @title= setting.')
if not link:
- raise ValueError, 'Missing @link= setting.'
+ raise ValueError('Missing @link= setting.')
if not desc:
- raise ValueError, 'Missing @desc= setting.'
+ raise ValueError('Missing @desc= setting.')
channel.appendChild(doc.createElement('title', textNode=title))
channel.appendChild(doc.createElement('link', textNode=link))
channel.appendChild(doc.createElement('description', textNode=desc))
@@ -153,7 +153,7 @@
for child in oldDocElement.childNodes:
if child.type != "element":
if child.value.strip():
- raise ValueError, 'Expected outer-level element, not text.'
+ raise ValueError('Expected outer-level element, not text.')
continue
if child.nodeName == 'h1':
@@ -161,24 +161,24 @@
elif child.nodeName == "h2":
link = len(child.childNodes) == 1 and child.childNodes[0]
if not link or link.type != 'element' or link.nodeName != 'a':
- raise ValueError, 'Each heading must be a link.'
+ raise ValueError('Each heading must be a link.')
titlenode = len(link.childNodes) == 1 and link.childNodes[0]
if not titlenode or titlenode.type != 'text':
- raise ValueError, 'Each heading link must contain a ' + \
- 'single text node.'
+ raise ValueError('Each heading link must contain a ' + \
+ 'single text node.')
heading = titlenode.value.strip()
# Combine the href with the linkbase.
assert 'href' in link.attributes
href = link.attribute_values['href']
if not linkbase.endswith('/'):
- raise ValueError, 'The @linkbase must be a directory: %s' % \
- linkbase
+ raise ValueError('The @linkbase must be a directory: %s' % \
+ linkbase)
href = linkbase + href
if href in guids:
- raise ValueError, "Duplicate link: %s" % href
+ raise ValueError("Duplicate link: %s" % href)
guids.append(href)
item = doc.createElement("item")
@@ -193,21 +193,21 @@
# The first paragraph is <p><em>pubDate</em></p>
em = len(child.childNodes) == 1 and child.childNodes[0]
if not em or em.type != 'element' or em.nodeName != 'em':
- raise ValueError, 'The first paragraph must contain ' + \
- 'only an <em>.'
+ raise ValueError('The first paragraph must contain ' + \
+ 'only an <em>.')
emchild = len(em.childNodes) == 1 and em.childNodes[0]
if not emchild or emchild.type != 'text':
- raise ValueError, "The first paragraph's em must " + \
- "contain only text."
+ raise ValueError("The first paragraph's em must " + \
+ "contain only text.")
pubdate = emchild.value
format = "%a, %d %b %Y %H:%M:%S +0000"
dateobj = datetime.datetime.strptime(pubdate, format)
normalized = dateobj.strftime(format)
if normalized != pubdate:
- raise ValueError, 'Encountered date %s but expected %s' % \
- (pubdate, normalized)
+ raise ValueError('Encountered date %s but expected %s' % \
+ (pubdate, normalized))
item.appendChild(doc.createElement('pubDate', emchild.value))
@@ -218,7 +218,7 @@
item_desc.appendChild(cdata)
else:
- raise ValueError, 'Unsupported node type: %s' % child.nodeName
+ raise ValueError('Unsupported node type: %s' % child.nodeName)
return doc.toxml()
def _preprocess(path):
@@ -227,13 +227,13 @@
# will resolve.
url = match.group(1).strip()
if '/' in url:
- raise ValueError, 'Inclusions cannot cross directories'
+ raise ValueError('Inclusions cannot cross directories')
# When including a file, update global settings and replace
# with contents.
includepath = _get_path_for_url(url, path)
if not includepath:
- raise ValueError, 'Unmatched URL: %s' % match.group(1)
+ raise ValueError('Unmatched URL: %s' % match.group(1))
settings, contents = _preprocess(includepath)
childsettings.update(settings)
return contents
@@ -291,7 +291,7 @@
page = open(template_path).read() % keywords
return 'text/html', page
else:
- raise ValueError, 'Invalid file type: %s' % path
+ raise ValueError('Invalid file type: %s' % path)
class _Handler(BaseHTTPServer.BaseHTTPRequestHandler):
def do_GET(self):
@@ -339,7 +339,7 @@
yield relpath
if not host or '/' in host:
- raise ValueError, 'Host must be sub.domain.com'
+ raise ValueError('Host must be sub.domain.com')
for relpath in findfiles(DOC_ROOT):
sourcepath = os.path.join(DOC_ROOT, relpath)
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mat...@us...> - 2013-10-02 23:23:27
|
Revision: 328
http://sourceforge.net/p/javascriptlint/code/328
Author: matthiasmiller
Date: 2013-10-02 23:23:24 +0000 (Wed, 02 Oct 2013)
Log Message:
-----------
pylint: clean up trailing whitespace
Modified Paths:
--------------
trunk/javascriptlint/conf.py
trunk/javascriptlint/lint.py
trunk/jsengine/parser/__init__.py
trunk/jsengine/structs.py
trunk/jsengine/tokenizer/__init__.py
trunk/test.py
Modified: trunk/javascriptlint/conf.py
===================================================================
--- trunk/javascriptlint/conf.py 2013-10-02 23:18:30 UTC (rev 327)
+++ trunk/javascriptlint/conf.py 2013-10-02 23:23:24 UTC (rev 328)
@@ -163,14 +163,14 @@
def load(self, enabled, parm):
if not enabled:
raise ConfError('Expected +.')
-
+
self.value = util.JSVersion.fromtype(parm)
if not self.value:
raise ConfError('Invalid JavaScript version: %s' % parm)
class Conf:
def __init__(self):
- recurse = BooleanSetting(False)
+ recurse = BooleanSetting(False)
self._settings = {
'recurse': recurse,
'output-format': StringSetting('__FILE__(__LINE__): __ERROR__'),
Modified: trunk/javascriptlint/lint.py
===================================================================
--- trunk/javascriptlint/lint.py 2013-10-02 23:18:30 UTC (rev 327)
+++ trunk/javascriptlint/lint.py 2013-10-02 23:23:24 UTC (rev 328)
@@ -19,7 +19,7 @@
'eof', 'comma', 'dot', 'semi', 'colon', 'lc', 'rc', 'lp', 'rb', 'assign',
'relop', 'hook', 'plus', 'minus', 'star', 'divop', 'eqop', 'shop', 'or',
'and', 'bitor', 'bitxor', 'bitand', 'else', 'try'
-)
+)
_globals = frozenset([
'Array', 'Boolean', 'Math', 'Number', 'String', 'RegExp', 'Script', 'Date',
@@ -27,7 +27,7 @@
'eval', 'NaN', 'Infinity',
'escape', 'unescape', 'uneval',
'decodeURI', 'encodeURI', 'decodeURIComponent', 'encodeURIComponent',
- 'Function', 'Object',
+ 'Function', 'Object',
'Error', 'InternalError', 'EvalError', 'RangeError', 'ReferenceError',
'SyntaxError', 'TypeError', 'URIError',
'arguments', 'undefined'
Modified: trunk/jsengine/parser/__init__.py
===================================================================
--- trunk/jsengine/parser/__init__.py 2013-10-02 23:18:30 UTC (rev 327)
+++ trunk/jsengine/parser/__init__.py 2013-10-02 23:23:24 UTC (rev 328)
@@ -86,7 +86,7 @@
x.startpos, x.endpos, None, [])
items[-1] = items[-1] or comma
- # Check for the end.
+ # Check for the end.
if t.peek().tok == tok.RBRACKET:
end_comma = comma
break
@@ -306,7 +306,7 @@
_MULTIPLICATIVE = {
tok.MUL: (kind.STAR, op.MUL),
tok.DIV: (kind.DIVOP, op.DIV),
- tok.MOD: (kind.DIVOP, op.MOD),
+ tok.MOD: (kind.DIVOP, op.MOD),
}
def _multiplicative_expression(t):
return _binary_expression(t, _MULTIPLICATIVE, _unary_expression)
@@ -391,7 +391,7 @@
t.expect(tok.LOGICAL_AND)
else:
break
-
+
while len(exprs) > 1:
right = exprs.pop()
left = exprs[-1]
@@ -408,7 +408,7 @@
t.expect(tok.LOGICAL_OR)
else:
break
-
+
while len(exprs) > 1:
right = exprs.pop()
left = exprs[-1]
@@ -467,7 +467,7 @@
kind_, op_ = _ASSIGNS[t.peek().tok]
t.advance()
right = _assignment_expression(t, allowin)
- return ParseNode(kind_, op_,
+ return ParseNode(kind_, op_,
left.startpos, right.endpos, None, [left, right])
else:
return left
@@ -607,7 +607,7 @@
op.FORIN if condition.kind == kind.IN else None,
for_startpos, body.endpos,
None, [condition, body])
-
+
def _continue_statement(t):
endtoken = t.expect(tok.CONTINUE)
startpos = endtoken.startpos
@@ -617,7 +617,7 @@
name = endtoken.atom
else:
name = None
- # TODO: Validate Scope Labels
+ # TODO: Validate Scope Labels
return _auto_semicolon(t, kind.CONTINUE, None, startpos, endtoken.endpos, name, [])
def _break_statement(t):
@@ -629,19 +629,19 @@
name = endtoken.atom
else:
name = None
- # TODO: Validate Scope Labels
+ # TODO: Validate Scope Labels
return _auto_semicolon(t, kind.BREAK, None, startpos, endtoken.endpos, name, [])
def _return_statement(t):
endtoken = t.expect(tok.RETURN)
startpos = endtoken.startpos
-
+
if t.peek_sameline().tok not in (tok.EOF, tok.EOL, tok.SEMI, tok.RBRACE):
expr = _expression(t, True)
endtoken = expr
else:
expr = None
- # TODO: Validate Scope Labels
+ # TODO: Validate Scope Labels
return _auto_semicolon(t, kind.RETURN, None, startpos, endtoken.endpos,
None, [expr])
@@ -672,7 +672,7 @@
case_kind = kind.DEFAULT
else:
raise JSSyntaxError(t.peek().startpos, 'invalid_case')
-
+
case_endpos = t.expect(tok.COLON).endpos
statements = []
@@ -692,7 +692,7 @@
ParseNode(kind.LC, None, statements_startpos,
statements_endpos, None, statements)
]))
-
+
rc_endpos = t.expect(tok.RBRACE).endpos
return ParseNode(kind.SWITCH, None, switch_startpos, rc_endpos,
None, [expr,
@@ -734,7 +734,7 @@
])
])
try_endpos = catch_endpos
-
+
if t.peek().tok == tok.FINALLY:
t.advance()
finally_node = _block_statement(t)
@@ -782,7 +782,7 @@
raise JSSyntaxError(x.startpos, 'unexpected_eof')
elif x.tok == tok.FUNCTION:
return _function_declaration(t, op.CLOSURE) #TODO: warn, since this is not reliable
-
+
elif x.tok not in (tok.LBRACE, tok.FUNCTION):
expr = _expression(t, True)
if expr.kind == tok.NAME and t.peek().tok == tok.COLON:
Modified: trunk/jsengine/structs.py
===================================================================
--- trunk/jsengine/structs.py 2013-10-02 23:18:30 UTC (rev 327)
+++ trunk/jsengine/structs.py 2013-10-02 23:23:24 UTC (rev 328)
@@ -112,7 +112,7 @@
self.endpos = end_pos
self.no_semi = no_semi
self.end_comma = end_comma
-
+
for i, kid in enumerate(self.kids):
if kid:
assert isinstance(kid, ParseNode)
Modified: trunk/jsengine/tokenizer/__init__.py
===================================================================
--- trunk/jsengine/tokenizer/__init__.py 2013-10-02 23:18:30 UTC (rev 327)
+++ trunk/jsengine/tokenizer/__init__.py 2013-10-02 23:23:24 UTC (rev 328)
@@ -41,7 +41,7 @@
"}": "RBRACE",
"(": "LPAREN",
")": "RPAREN",
- "[": "LBRACKET",
+ "[": "LBRACKET",
"]": "RBRACKET",
".": "DOT",
";": "SEMI",
@@ -58,7 +58,7 @@
"!": "LOGICAL_NOT",
"~": "BIT_NOT",
"?": "QUESTION",
- ":": "COLON",
+ ":": "COLON",
"=": "ASSIGN",
"/": "DIV",
"!": "LOGICAL_NOT",
@@ -159,7 +159,7 @@
def getpos(self, offset=0):
return self._nodepositions.from_offset(self._pos+offset)
-
+
def watch_reads(self):
self._watched_pos = self._pos
@@ -316,7 +316,7 @@
def _next(self, parse_regexp=False):
stream = self._stream
-
+
if stream.eof():
return Token(tok.EOF)
@@ -331,10 +331,10 @@
elif stream.readif(1, _WHITESPACE):
pass
else:
- break
+ break
if linebreak:
return Token(tok.EOL)
- else:
+ else:
return Token(tok.SPACE)
# COMMENTS
Modified: trunk/test.py
===================================================================
--- trunk/test.py 2013-10-02 23:18:30 UTC (rev 327)
+++ trunk/test.py 2013-10-02 23:23:24 UTC (rev 328)
@@ -96,7 +96,7 @@
class _CustomLintReporter(TextReporter):
line_format = '{path}({line}): [{msg_id}({symbol}){obj}] {msg}'
def __init__(self):
- TextReporter.__init__(self)
+ TextReporter.__init__(self)
self.msg_count = 0
def write_message(self, msg):
@@ -129,7 +129,6 @@
'C0103', # Invalid name "%s" (should match %s)
'C0202', # Class method should have "cls" as first argument
'C0301', # Line too long (%s/%s)
- 'C0303', # Trailing whitespace
'C0321', # More than one statement on a single line
'C0323', # Operator not followed by a space
'C0324', # Comma not followed by a space
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mat...@us...> - 2013-10-02 23:27:22
|
Revision: 329
http://sourceforge.net/p/javascriptlint/code/329
Author: matthiasmiller
Date: 2013-10-02 23:27:18 +0000 (Wed, 02 Oct 2013)
Log Message:
-----------
pylint: fix more whitespace issues
Modified Paths:
--------------
trunk/javascriptlint/jsparse.py
trunk/javascriptlint/warnings.py
trunk/jsengine/parser/__init__.py
trunk/jsengine/structs.py
trunk/test.py
trunk/www.py
Modified: trunk/javascriptlint/jsparse.py
===================================================================
--- trunk/javascriptlint/jsparse.py 2013-10-02 23:23:24 UTC (rev 328)
+++ trunk/javascriptlint/jsparse.py 2013-10-02 23:27:18 UTC (rev 329)
@@ -55,7 +55,7 @@
""" All node positions will be relative to startpos. This allows scripts
to be embedded in a file (for example, HTML).
"""
- startpos = startpos or NodePos(0,0)
+ startpos = startpos or NodePos(0, 0)
jsversion = jsversion or JSVersion.default()
assert isvalidversion(jsversion), jsversion
if jsversion.e4x:
@@ -173,7 +173,7 @@
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))
+ 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))
@@ -185,21 +185,21 @@
def testAdd(self):
r = NodeRanges()
r.add(5, 10)
- self.assertEquals(r._offsets, [5,11])
+ self.assertEquals(r._offsets, [5, 11])
r.add(15, 20)
- self.assertEquals(r._offsets, [5,11,15,21])
- r.add(21,22)
- self.assertEquals(r._offsets, [5,11,15,23])
- r.add(4,5)
- self.assertEquals(r._offsets, [4,11,15,23])
- r.add(9,11)
- self.assertEquals(r._offsets, [4,12,15,23])
- r.add(10,20)
- self.assertEquals(r._offsets, [4,23])
- r.add(4,22)
- self.assertEquals(r._offsets, [4,23])
- r.add(30,30)
- self.assertEquals(r._offsets, [4,23,30,31])
+ self.assertEquals(r._offsets, [5, 11, 15, 21])
+ r.add(21, 22)
+ self.assertEquals(r._offsets, [5, 11, 15, 23])
+ r.add(4, 5)
+ self.assertEquals(r._offsets, [4, 11, 15, 23])
+ r.add(9, 11)
+ self.assertEquals(r._offsets, [4, 12, 15, 23])
+ r.add(10, 20)
+ self.assertEquals(r._offsets, [4, 23])
+ r.add(4, 22)
+ self.assertEquals(r._offsets, [4, 23])
+ r.add(30, 30)
+ self.assertEquals(r._offsets, [4, 23, 30, 31])
def testHas(self):
r = NodeRanges()
r.add(5, 10)
@@ -239,8 +239,8 @@
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', {}))
+ 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, None, startpos)
@@ -248,24 +248,24 @@
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))
+ 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, None, startpos)
comment, = findcomments(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))
+ 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/javascriptlint/warnings.py
===================================================================
--- trunk/javascriptlint/warnings.py 2013-10-02 23:23:24 UTC (rev 328)
+++ trunk/javascriptlint/warnings.py 2013-10-02 23:27:18 UTC (rev 329)
@@ -290,7 +290,7 @@
def with_statement(node):
raise LintWarning(node)
-@lookfor(tok.EQOP,tok.RELOP)
+@lookfor(tok.EQOP, tok.RELOP)
def useless_comparison(node):
for lvalue, rvalue in itertools.combinations(node.kids, 2):
if lvalue.is_equivalent(rvalue):
Modified: trunk/jsengine/parser/__init__.py
===================================================================
--- trunk/jsengine/parser/__init__.py 2013-10-02 23:23:24 UTC (rev 328)
+++ trunk/jsengine/parser/__init__.py 2013-10-02 23:27:18 UTC (rev 329)
@@ -854,7 +854,7 @@
try:
parsestring('/*')
except JSSyntaxError as error:
- self.assertEqual(error.pos, NodePos(0,1))
+ self.assertEqual(error.pos, NodePos(0, 1))
else:
self.assert_(False)
def testObjectEndComma(self):
Modified: trunk/jsengine/structs.py
===================================================================
--- trunk/jsengine/structs.py 2013-10-02 23:23:24 UTC (rev 328)
+++ trunk/jsengine/structs.py 2013-10-02 23:27:18 UTC (rev 329)
@@ -63,7 +63,7 @@
end = self._offsets[j]
j += 1
- self._offsets[i:j] = [start,end]
+ self._offsets[i:j] = [start, end]
def has(self, pos):
return bisect.bisect_right(self._offsets, pos) % 2 == 1
Modified: trunk/test.py
===================================================================
--- trunk/test.py 2013-10-02 23:23:24 UTC (rev 328)
+++ trunk/test.py 2013-10-02 23:27:18 UTC (rev 329)
@@ -130,8 +130,6 @@
'C0202', # Class method should have "cls" as first argument
'C0301', # Line too long (%s/%s)
'C0321', # More than one statement on a single line
- 'C0323', # Operator not followed by a space
- 'C0324', # Comma not followed by a space
'C1001', # Old style class
'E0602', # Undefined variable %r
'E1101', # %s %r has no %r member
Modified: trunk/www.py
===================================================================
--- trunk/www.py 2013-10-02 23:23:24 UTC (rev 328)
+++ trunk/www.py 2013-10-02 23:27:18 UTC (rev 329)
@@ -361,12 +361,12 @@
if action == 'build':
build(host)
return
- print >>sys.stderr, """\
+ sys.stderr.write("""\
Usage: www.py [server|build] <host>
server runs a test server on localhost
build generates static HTML files from the markup
-"""
+""")
sys.exit(1)
if __name__ == '__main__':
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mat...@us...> - 2013-10-03 19:16:49
|
Revision: 330
http://sourceforge.net/p/javascriptlint/code/330
Author: matthiasmiller
Date: 2013-10-03 19:16:44 +0000 (Thu, 03 Oct 2013)
Log Message:
-----------
Embed version number and revision.
Modified Paths:
--------------
trunk/javascriptlint/conf.py
trunk/javascriptlint/jsl.py
trunk/setup.py
Added Paths:
-----------
trunk/javascriptlint/version.py
Modified: trunk/javascriptlint/conf.py
===================================================================
--- trunk/javascriptlint/conf.py 2013-10-02 23:27:18 UTC (rev 329)
+++ trunk/javascriptlint/conf.py 2013-10-03 19:16:44 UTC (rev 330)
@@ -4,6 +4,7 @@
import fs
import util
+import version
import warnings
_DISABLED_WARNINGS = (
@@ -100,7 +101,7 @@
# or "+process Folder\Path\*.htm".
#
""" % {
- 'version': '', # TODO
+ 'version': version.version,
'warnings': _getwarningsconf(),
}
Modified: trunk/javascriptlint/jsl.py
===================================================================
--- trunk/javascriptlint/jsl.py 2013-10-02 23:27:18 UTC (rev 329)
+++ trunk/javascriptlint/jsl.py 2013-10-03 19:16:44 UTC (rev 330)
@@ -14,6 +14,7 @@
import jsparse
import lint
import util
+import version
_lint_results = {
'warnings': 0,
@@ -48,8 +49,7 @@
return paths or [path]
def printlogo():
- # TODO: Print version number.
- print "JavaScript Lint"
+ print "JavaScript Lint %s" % version.version
print "Developed by Matthias Miller (http://www.JavaScriptLint.com)"
def _profile_enabled(func, *args, **kwargs):
Added: trunk/javascriptlint/version.py
===================================================================
--- trunk/javascriptlint/version.py (rev 0)
+++ trunk/javascriptlint/version.py 2013-10-03 19:16:44 UTC (rev 330)
@@ -0,0 +1,19 @@
+import os.path
+import subprocess
+
+try:
+ from __svnversion__ import version
+except ImportError:
+ def _getrevnum():
+ path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+ p = subprocess.Popen(['svnversion', path], stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ stdout, stderr = p.communicate()
+ if p.returncode != 0:
+ raise _BuildError('Error running svnversion: %s' % stderr)
+ version = stdout.strip().rstrip('M')
+ version = version.rpartition(':')[-1]
+ return int(version)
+
+ version = '0.5.0/r%i' % _getrevnum()
+
Modified: trunk/setup.py
===================================================================
--- trunk/setup.py 2013-10-02 23:27:18 UTC (rev 329)
+++ trunk/setup.py 2013-10-03 19:16:44 UTC (rev 330)
@@ -7,20 +7,12 @@
import subprocess
import sys
+from javascriptlint import version
+
class _BuildError(Exception):
pass
-def _getrevnum():
- path = os.path.dirname(os.path.abspath(__file__))
- p = subprocess.Popen(['svnversion', path], stdin=subprocess.PIPE,
- stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- stdout, stderr = p.communicate()
- if p.returncode != 0:
- raise _BuildError('Error running svnversion: %s' % stderr)
- version = stdout.strip().rstrip('M')
- return int(version)
-
-if __name__ == '__main__':
+def _setup():
cmdclass = {
'build': distutils.command.build.build,
'clean': distutils.command.clean.clean,
@@ -28,12 +20,12 @@
args = {}
args.update(
name = 'javascriptlint',
- version = '0.0.0.%i' % _getrevnum(),
+ version = version.version,
author = 'Matthias Miller',
author_email = 'in...@ja...',
url = 'http://www.javascriptlint.com/',
cmdclass = cmdclass,
- description = 'JavaScript Lint (pyjsl beta r%i)' % _getrevnum(),
+ description = 'JavaScript Lint %s' % version.version,
packages = ['javascriptlint'],
scripts = ['jsl']
)
@@ -64,3 +56,18 @@
)
setup(**args)
+def _main():
+ # Create a temporary __svnversion__.py to bundle the version
+ path = os.path.join(os.path.dirname(os.path.abspath(__file__)),
+ 'javascriptlint', '__svnversion__.py')
+ with open(path, 'w') as f:
+ f.write('version = %r' % version.version)
+ try:
+ _setup()
+ finally:
+ os.unlink(path)
+ if os.path.exists(path + 'c'):
+ os.unlink(path + 'c')
+
+if __name__ == '__main__':
+ _main()
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mat...@us...> - 2013-10-03 20:13:40
|
Revision: 333
http://sourceforge.net/p/javascriptlint/code/333
Author: matthiasmiller
Date: 2013-10-03 20:13:37 +0000 (Thu, 03 Oct 2013)
Log Message:
-----------
Fix parsing numbers with exponents.
Modified Paths:
--------------
trunk/jsengine/tokenizer/__init__.py
trunk/test.py
Added Paths:
-----------
trunk/tests/bugs/numbers.js
Modified: trunk/jsengine/tokenizer/__init__.py
===================================================================
--- trunk/jsengine/tokenizer/__init__.py 2013-10-03 19:48:25 UTC (rev 332)
+++ trunk/jsengine/tokenizer/__init__.py 2013-10-03 20:13:37 UTC (rev 333)
@@ -397,7 +397,8 @@
if stream.readif(1, 'eE'):
stream.readif(1, '+-')
- stream.require(_DIGITS)
+ if not stream.readif(1, _DIGITS):
+ raise JSSyntaxError(stream.getpos(), 'syntax_error')
while stream.readif(1, _DIGITS):
pass
Modified: trunk/test.py
===================================================================
--- trunk/test.py 2013-10-03 19:48:25 UTC (rev 332)
+++ trunk/test.py 2013-10-03 20:13:37 UTC (rev 333)
@@ -105,6 +105,10 @@
def _get_python_modules(dir_):
for root, dirs, files in os.walk(dir_):
+ for exclude in ('build', 'dist'):
+ if exclude in dirs:
+ build.remove(exclude)
+
if '.svn' in dirs:
dirs.remove('.svn')
for name in files:
Added: trunk/tests/bugs/numbers.js
===================================================================
--- trunk/tests/bugs/numbers.js (rev 0)
+++ trunk/tests/bugs/numbers.js 2013-10-03 20:13:37 UTC (rev 333)
@@ -0,0 +1,5 @@
+function number() {
+ var i = 1.1e10;
+ i = 1.1e+10;
+ i = 1.1e-10;
+}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mat...@us...> - 2013-10-08 16:36:50
|
Revision: 334
http://sourceforge.net/p/javascriptlint/code/334
Author: matthiasmiller
Date: 2013-10-08 16:36:44 +0000 (Tue, 08 Oct 2013)
Log Message:
-----------
Change the parser to only use offsets internally and to convert offsets to line/col only when reporting errors.
Modified Paths:
--------------
trunk/javascriptlint/htmlparse.py
trunk/javascriptlint/jsparse.py
trunk/javascriptlint/lint.py
trunk/javascriptlint/warnings.py
trunk/jsengine/__init__.py
trunk/jsengine/parser/__init__.py
trunk/jsengine/structs.py
trunk/jsengine/tokenizer/__init__.py
trunk/test.py
Modified: trunk/javascriptlint/htmlparse.py
===================================================================
--- trunk/javascriptlint/htmlparse.py 2013-10-03 20:13:37 UTC (rev 333)
+++ trunk/javascriptlint/htmlparse.py 2013-10-08 16:36:44 UTC (rev 334)
@@ -2,18 +2,25 @@
import HTMLParser
import unittest
+from jsengine.structs import NodePos, NodePositions
+
class _Parser(HTMLParser.HTMLParser):
def __init__(self):
HTMLParser.HTMLParser.__init__(self)
self._tags = []
+ self._node_positions = None
+ def feed(self, data):
+ # Reset line numbers whenever we get data.
+ self._node_positions = None
+ HTMLParser.HTMLParser.feed(self, data)
+
def handle_starttag(self, tag, attributes):
if tag.lower() == 'script':
attr = dict(attributes)
self._tags.append({
'type': 'start',
- 'lineno': self.lineno,
- 'offset': self.offset,
+ 'offset': self._getoffset(),
'len': len(self.get_starttag_text()),
'attr': attr
})
@@ -22,8 +29,7 @@
if tag.lower() == 'script':
self._tags.append({
'type': 'end',
- 'lineno': self.lineno,
- 'offset': self.offset,
+ 'offset': self._getoffset(),
})
def unknown_decl(self, data):
@@ -33,9 +39,16 @@
def gettags(self):
return self._tags
+ def _getoffset(self):
+ # htmlparse returns 1-based line numbers. Calculate the offset of the
+ # script's contents.
+ if self._node_positions is None:
+ self._node_positions = NodePositions(self.rawdata)
+ pos = NodePos(self.lineno - 1, self.offset)
+ return self._node_positions.to_offset(pos)
+
+
def findscripttags(s):
- """ Note that the lineno is 1-based.
- """
parser = _Parser()
parser.feed(s)
parser.close()
Modified: trunk/javascriptlint/jsparse.py
===================================================================
--- trunk/javascriptlint/jsparse.py 2013-10-03 20:13:37 UTC (rev 333)
+++ trunk/javascriptlint/jsparse.py 2013-10-08 16:36:44 UTC (rev 334)
@@ -16,7 +16,8 @@
return True
return jsengine.parser.is_valid_version(jsversion.version)
-def findpossiblecomments(script, node_positions):
+def findpossiblecomments(script, script_offset):
+ assert not script_offset is None
pos = 0
single_line_re = r"//[^\r\n]*"
multi_line_re = r"/\*(.*?)\*/"
@@ -41,38 +42,34 @@
start_offset = match.start()
end_offset = match.end()-1
- start_pos = node_positions.from_offset(start_offset)
- end_pos = node_positions.from_offset(end_offset)
- comment_node = ParseNode(kind.COMMENT, opcode, start_pos, end_pos,
- comment_text, [])
+ comment_node = ParseNode(kind.COMMENT, opcode,
+ script_offset + start_offset,
+ script_offset + end_offset, comment_text, [])
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, jsversion, 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 parse(script, jsversion, error_callback, start_offset=0):
+ """ All node positions will be relative to start_offset. This allows
+ scripts to be embedded in a file (for example, HTML).
"""
- startpos = startpos or NodePos(0, 0)
+ assert not start_offset is None
jsversion = jsversion or JSVersion.default()
assert isvalidversion(jsversion), jsversion
if jsversion.e4x:
- error_callback(startpos.line, startpos.col, 'e4x_deprecated', {})
+ error_callback(start_offset, 'e4x_deprecated', {})
return jsengine.parser.parse(script, jsversion.version,
- error_callback,
- startpos)
+ error_callback, start_offset)
-def filtercomments(possible_comments, node_positions, root_node):
+def filtercomments(possible_comments, root_node):
comment_ignore_ranges = NodeRanges()
def process(node):
if node.kind == tok.STRING or \
(node.kind == tok.OBJECT and node.opcode == op.REGEXP):
- start_offset = node_positions.to_offset(node.start_pos())
- end_offset = node_positions.to_offset(node.end_pos())
- comment_ignore_ranges.add(start_offset, end_offset)
+ comment_ignore_ranges.add(node.start_offset, node.end_offset)
for kid in node.kids:
if kid:
process(kid)
@@ -80,25 +77,22 @@
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):
+ if comment_ignore_ranges.has(comment.start_offset):
continue
- comment_ignore_ranges.add(start_offset, end_offset)
+ comment_ignore_ranges.add(comment.start_offset, comment.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 findcomments(script, root_node, start_offset=0):
+ possible_comments = findpossiblecomments(script, start_offset)
+ return filtercomments(possible_comments, root_node)
def is_compilable_unit(script, jsversion):
jsversion = jsversion or JSVersion.default()
assert isvalidversion(jsversion)
return jsengine.parser.is_compilable_unit(script, jsversion.version)
-def _dump_node(node, depth=0):
+def _dump_node(node, node_positions, depth=0):
if node is None:
print ' '*depth,
print '(None)'
@@ -107,7 +101,8 @@
print ' '*depth,
print '%s, %s' % (repr(node.kind), repr(node.opcode))
print ' '*depth,
- print '%s - %s' % (node.start_pos(), node.end_pos())
+ print '%s - %s' % (node_positions.from_offset(node.start_offset),
+ node_positions.from_offset(node.end_offset))
if hasattr(node, 'atom'):
print ' '*depth,
print 'atom: %s' % node.atom
@@ -116,13 +111,14 @@
print '(no semicolon)'
print
for node in node.kids:
- _dump_node(node, depth+1)
+ _dump_node(node, node_positions, depth+1)
def dump_tree(script):
def error_callback(line, col, msg, msg_args):
print '(%i, %i): %s', (line, col, msg)
node = parse(script, None, error_callback)
- _dump_node(node)
+ node_positions = NodePositions(script)
+ _dump_node(node, node_positions)
class TestComments(unittest.TestCase):
def _test(self, script, expected_comments):
@@ -230,42 +226,42 @@
class TestLineOffset(unittest.TestCase):
def testErrorPos(self):
- def geterror(script, startpos):
+ def geterror(script, start_offset):
errors = []
- def onerror(line, col, msg, msg_args):
- errors.append((line, col, msg, msg_args))
- parse(script, None, onerror, startpos)
+ def onerror(offset, msg, msg_args):
+ errors.append((offset, msg, msg_args))
+ parse(script, None, onerror, start_offset)
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', {}))
+ self.assertEquals(geterror(' ?', 0), (1, 'syntax_error', {}))
+ self.assertEquals(geterror('\n ?', 0), (2, 'syntax_error', {}))
+ self.assertEquals(geterror(' ?', 2), (3, 'syntax_error', {}))
+ self.assertEquals(geterror('\n ?', 2), (4, 'syntax_error', {}))
def testNodePos(self):
- def getnodepos(script, startpos):
- root = parse(script, None, None, startpos)
+ def getnodepos(script, start_offset):
+ root = parse(script, None, None, start_offset)
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))
+ return var.start_offset
+ self.assertEquals(getnodepos('var x;', 0), 0)
+ self.assertEquals(getnodepos(' var x;', 0), 1)
+ self.assertEquals(getnodepos('\n\n var x;', 0), 3)
+ self.assertEquals(getnodepos('var x;', 7), 7)
+ self.assertEquals(getnodepos(' var x;', 7), 8)
+ self.assertEquals(getnodepos('\n\n var x;', 7), 10)
def testComments(self):
- def testcomment(comment, startpos, expectedpos):
+ def testcomment(comment, startpos, expected_offset):
root = parse(comment, None, None, startpos)
comment, = findcomments(comment, root, startpos)
- self.assertEquals(comment.start_pos(), expectedpos)
+ self.assertEquals(comment.start_offset, expected_offset)
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))
+ testcomment(comment, 0, 0)
+ testcomment(' %s' % comment, 0, 1)
+ testcomment('\n\n %s' % comment, 0, 3)
+ testcomment('%s' % comment, 7, 7)
+ testcomment(' %s' % comment, 7, 8)
+ testcomment('\n\n %s' % comment, 7, 10)
if __name__ == '__main__':
unittest.main()
Modified: trunk/javascriptlint/lint.py
===================================================================
--- trunk/javascriptlint/lint.py 2013-10-03 20:13:37 UTC (rev 333)
+++ trunk/javascriptlint/lint.py 2013-10-08 16:36:44 UTC (rev 334)
@@ -140,7 +140,7 @@
# 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())
+ unreferenced.sort(key=lambda x: x[2].start_offset)
return {
'unreferenced': unreferenced,
@@ -214,8 +214,8 @@
# 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()):
+ if (node.start_offset >= self._node.start_offset and \
+ node.end_offset <= self._node.end_offset):
return self
class _Script:
@@ -245,7 +245,6 @@
def _findhtmlscripts(contents, default_version):
starttag = None
- nodepos = jsparse.NodePositions(contents)
for tag in htmlparse.findscripttags(contents):
if tag['type'] == 'start':
# Ignore nested start tags.
@@ -265,13 +264,9 @@
# htmlparse returns 1-based line numbers. Calculate the
# position of the script's contents.
- tagpos = jsparse.NodePos(starttag['lineno']-1, starttag['offset'])
- tagoffset = nodepos.to_offset(tagpos)
- startoffset = tagoffset + starttag['len']
- startpos = nodepos.from_offset(startoffset)
- endpos = jsparse.NodePos(tag['lineno']-1, tag['offset'])
- endoffset = nodepos.to_offset(endpos)
- script = contents[startoffset:endoffset]
+ start_offset = starttag['offset'] + starttag['len']
+ end_offset = tag['offset']
+ script = contents[start_offset:end_offset]
if not jsparse.isvalidversion(starttag['jsversion']) or \
jsparse.is_compilable_unit(script, starttag['jsversion']):
@@ -279,7 +274,7 @@
yield {
'type': 'inline',
'jsversion': starttag['jsversion'],
- 'pos': startpos,
+ 'offset': start_offset,
'contents': script,
}
starttag = None
@@ -294,8 +289,9 @@
import_path = import_path.replace('\\', os.sep)
import_path = os.path.join(os.path.dirname(path), import_path)
return lint_file(import_path, 'js', jsversion, encoding)
- def _lint_error(*args):
- return lint_error(normpath, *args)
+ def _lint_error(offset, errname, errdesc):
+ pos = node_positions.from_offset(offset)
+ return lint_error(normpath, pos.line, pos.col, errname, errdesc)
normpath = fs.normpath(path)
if normpath in lint_cache:
@@ -307,12 +303,13 @@
try:
contents = fs.readfile(path, encoding)
except IOError, error:
- _lint_error(0, 0, 'io_error', unicode(error))
+ lint_error(normpath, 0, 0, 'io_error', unicode(error))
return lint_cache[normpath]
+ node_positions = jsparse.NodePositions(contents)
script_parts = []
if kind == 'js':
- script_parts.append((None, jsversion or conf['default-version'], contents))
+ script_parts.append((0, jsversion or conf['default-version'], contents))
elif kind == 'html':
assert jsversion is None
for script in _findhtmlscripts(contents, conf['default-version']):
@@ -324,7 +321,7 @@
other = import_script(script['src'], script['jsversion'])
lint_cache[normpath].importscript(other)
elif script['type'] == 'inline':
- script_parts.append((script['pos'], script['jsversion'],
+ script_parts.append((script['offset'], script['jsversion'],
script['contents']))
else:
assert False, 'Invalid internal script type %s' % \
@@ -343,18 +340,18 @@
else:
lint_file(path, 'js', None, encoding)
-def _lint_script_part(scriptpos, jsversion, script, script_cache, conf,
+def _lint_script_part(script_offset, jsversion, script, script_cache, conf,
ignores, report_native, report_lint, import_callback):
- def parse_error(row, col, msg, msg_args):
+ def parse_error(offset, msg, msg_args):
if not msg in ('anon_no_return_value', 'no_return_value',
'redeclared_var', 'var_hides_arg'):
- parse_errors.append((jsparse.NodePos(row, col), msg, msg_args))
+ parse_errors.append((offset, msg, msg_args))
- def report(node, errname, pos=None, **errargs):
+ def report(node, errname, offset=0, **errargs):
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():
+ if pass_.start_offset > node.start_offset and \
+ pass_.end_offset < node.end_offset:
passes.remove(pass_)
return
@@ -363,12 +360,12 @@
# 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()
+ expectedfallthru = prevnode.end_offset, node.start_offset
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()
+ expectedfallthru = node.end_offset, node.parent.end_offset
else:
expectedfallthru = None
@@ -377,11 +374,11 @@
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:
+ if fallthru.start_offset > start and fallthru.end_offset < end:
fallthrus.remove(fallthru)
return
- report_lint(node, errname, pos, **errargs)
+ report_lint(node, errname, offset, **errargs)
parse_errors = []
declares = []
@@ -390,8 +387,7 @@
fallthrus = []
passes = []
- node_positions = jsparse.NodePositions(script, scriptpos)
- possible_comments = jsparse.findpossiblecomments(script, node_positions)
+ possible_comments = jsparse.findpossiblecomments(script, script_offset)
# Check control comments for the correct version. It may be this comment
# isn't a valid comment (for example, it might be inside a string literal)
@@ -410,18 +406,18 @@
report(node, 'unsupported_version', version=parms)
if not jsparse.isvalidversion(jsversion):
- report_lint(jsversionnode, 'unsupported_version', scriptpos,
+ report_lint(jsversionnode, 'unsupported_version', script_offset,
version=jsversion.version)
return
- root = jsparse.parse(script, jsversion, parse_error, scriptpos)
+ root = jsparse.parse(script, jsversion, parse_error, script_offset)
if not root:
# Report errors and quit.
- for pos, msg, msg_args in parse_errors:
- report_native(pos, msg, msg_args)
+ for offset, msg, msg_args in parse_errors:
+ report_native(offset, msg, msg_args)
return
- comments = jsparse.filtercomments(possible_comments, node_positions, root)
+ comments = jsparse.filtercomments(possible_comments, root)
if jsversionnode is not None and jsversionnode not in comments:
# TODO
@@ -449,7 +445,7 @@
start_ignore = node
elif keyword == 'end':
if start_ignore:
- ignores.append((start_ignore.start_pos(), node.end_pos()))
+ ignores.append((start_ignore.start_offset, node.end_offset))
start_ignore = None
else:
report(node, 'mismatch_ctrl_comments')
@@ -471,8 +467,8 @@
# Report at the actual error of the location. Add two
# characters for the opening two characters.
if nested_comment >= 0:
- pos = node_positions.from_offset(node_positions.to_offset(comment.start_pos()) + 2 + nested_comment)
- report(comment, 'nested_comment', pos=pos)
+ offset = comment.start_offset + 2 + nested_comment
+ report(comment, 'nested_comment', offset=offset)
if comment.atom.lower().startswith('jsl:'):
report(comment, 'jsl_cc_not_understood')
elif comment.atom.startswith('@'):
@@ -481,8 +477,8 @@
report(start_ignore, 'mismatch_ctrl_comments')
# Wait to report parse errors until loading jsl:ignore directives.
- for pos, msg in parse_errors:
- report_native(pos, msg)
+ for offset, msg in parse_errors:
+ report_native(offset, msg)
# Find all visitors and convert them into "onpush" callbacks that call "report"
visitors = {
@@ -516,15 +512,15 @@
unused_scope.set_unused(name, node)
def _lint_script_parts(script_parts, script_cache, lint_error, conf, import_callback):
- def report_lint(node, errname, pos=None, **errargs):
+ def report_lint(node, errname, offset=0, **errargs):
errdesc = warnings.format_error(errname, **errargs)
- _report(pos or node.start_pos(), errname, errdesc, True)
+ _report(offset or node.start_offset, errname, errdesc, True)
- def report_native(pos, errname, errargs):
+ def report_native(offset, errname, errargs):
errdesc = warnings.format_error(errname, **errargs)
- _report(pos, errname, errdesc, False)
+ _report(offset, errname, errdesc, False)
- def _report(pos, errname, errdesc, require_key):
+ def _report(offset, errname, errdesc, require_key):
try:
if not conf[errname]:
return
@@ -533,14 +529,14 @@
raise
for start, end in ignores:
- if pos >= start and pos <= end:
+ if offset >= start and offset <= end:
return
- return lint_error(pos.line, pos.col, errname, errdesc)
+ return lint_error(offset, errname, errdesc)
- for scriptpos, jsversion, script in script_parts:
+ for script_offset, jsversion, script in script_parts:
ignores = []
- _lint_script_part(scriptpos, jsversion, script, script_cache, conf, ignores,
+ _lint_script_part(script_offset, jsversion, script, script_cache, conf, ignores,
report_native, report_lint, import_callback)
scope = script_cache.scope
@@ -576,10 +572,10 @@
# TODO: This is ugly hardcoding to improve the error positioning of
# "missing_semicolon" errors.
if visitor.warning in ('missing_semicolon', 'missing_semicolon_for_lambda'):
- pos = warning.node.end_pos()
+ offset = warning.node.end_offset
else:
- pos = None
- report(warning.node, visitor.warning, pos=pos, **warning.errargs)
+ offset = None
+ report(warning.node, visitor.warning, offset=offset, **warning.errargs)
return onpush
def _warn_or_declare(scope, name, type_, node, report):
Modified: trunk/javascriptlint/warnings.py
===================================================================
--- trunk/javascriptlint/warnings.py 2013-10-03 20:13:37 UTC (rev 333)
+++ trunk/javascriptlint/warnings.py 2013-10-08 16:36:44 UTC (rev 334)
@@ -584,7 +584,7 @@
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())
+ returns.sort(key=lambda node: node.start_offset)
if returns:
raise LintWarning(returns[0], name=name)
# Warn if the function sometimes exits naturally.
Modified: trunk/jsengine/__init__.py
===================================================================
--- trunk/jsengine/__init__.py 2013-10-03 20:13:37 UTC (rev 333)
+++ trunk/jsengine/__init__.py 2013-10-08 16:36:44 UTC (rev 334)
@@ -10,12 +10,12 @@
)
class JSSyntaxError(BaseException):
- def __init__(self, pos, msg, msg_args=None):
+ def __init__(self, offset, msg, msg_args=None):
assert msg in _MESSAGES, msg
- self.pos = pos
+ self.offset = offset
self.msg = msg
self.msg_args = msg_args or {}
def __unicode__(self):
- return '%s: %s' % (self.pos, self.msg)
+ return '%s: %s' % (self.offset, self.msg)
def __repr__(self):
- return 'JSSyntaxError(%r, %r, %r)' % (self.pos, self.msg. self.msg_args)
+ return 'JSSyntaxError(%r, %r, %r)' % (self.offset, self.msg. self.msg_args)
Modified: trunk/jsengine/parser/__init__.py
===================================================================
--- trunk/jsengine/parser/__init__.py 2013-10-03 20:13:37 UTC (rev 333)
+++ trunk/jsengine/parser/__init__.py 2013-10-08 16:36:44 UTC (rev 334)
@@ -22,16 +22,16 @@
"1.7",
]
-def _auto_semicolon(t, kind_, op_, startpos, endpos, atom, kids):
+def _auto_semicolon(t, kind_, op_, start_offset, end_offset, atom, kids):
nosemi = False
if t.peek_sameline().tok not in (tok.EOF, tok.EOL, tok.RBRACE):
x = t.advance()
if x.tok != tok.SEMI:
- raise JSSyntaxError(x.startpos, 'semi_before_stmnt')
- endpos = x.endpos
+ raise JSSyntaxError(x.start_offset, 'semi_before_stmnt')
+ end_offset = x.end_offset
else:
nosemi = True
- return ParseNode(kind_, op_, startpos, endpos, atom, kids, nosemi)
+ return ParseNode(kind_, op_, start_offset, end_offset, atom, kids, nosemi)
def _function_arglist(t):
fn_args = []
@@ -39,8 +39,8 @@
while True:
x = t.expect(tok.NAME)
fn_args.append(ParseNode(kind.NAME, op.ARGNAME,
- x.startpos,
- x.endpos, x.atom, []))
+ x.start_offset,
+ x.end_offset, x.atom, []))
if t.peek().tok == tok.COMMA:
t.advance()
else:
@@ -50,23 +50,23 @@
def _primary_expression(t):
x = t.next_withregexp()
if x.tok == tok.THIS:
- return ParseNode(kind.PRIMARY, op.THIS, x.startpos, x.endpos, None, [])
+ return ParseNode(kind.PRIMARY, op.THIS, x.start_offset, x.end_offset, None, [])
elif x.tok == tok.NAME:
- return ParseNode(kind.NAME, op.NAME, x.startpos, x.endpos, x.atom, [None])
+ return ParseNode(kind.NAME, op.NAME, x.start_offset, x.end_offset, x.atom, [None])
elif x.tok == tok.NULL:
- return ParseNode(kind.PRIMARY, op.NULL, x.startpos, x.endpos, None, [])
+ return ParseNode(kind.PRIMARY, op.NULL, x.start_offset, x.end_offset, None, [])
elif x.tok == tok.TRUE:
- return ParseNode(kind.PRIMARY, op.TRUE, x.startpos, x.endpos, None, [])
+ return ParseNode(kind.PRIMARY, op.TRUE, x.start_offset, x.end_offset, None, [])
elif x.tok == tok.FALSE:
- return ParseNode(kind.PRIMARY, op.FALSE, x.startpos, x.endpos, None, [])
+ return ParseNode(kind.PRIMARY, op.FALSE, x.start_offset, x.end_offset, None, [])
elif x.tok == tok.STRING:
- return ParseNode(kind.STRING, op.STRING, x.startpos, x.endpos, x.atom, [])
+ return ParseNode(kind.STRING, op.STRING, x.start_offset, x.end_offset, x.atom, [])
elif x.tok == tok.REGEXP:
- return ParseNode(kind.OBJECT, op.REGEXP, x.startpos, x.endpos, None, [])
+ return ParseNode(kind.OBJECT, op.REGEXP, x.start_offset, x.end_offset, None, [])
elif x.tok == tok.NUMBER:
- return ParseNode(kind.NUMBER, None, x.startpos, x.endpos, x.atom, [])
+ return ParseNode(kind.NUMBER, None, x.start_offset, x.end_offset, x.atom, [])
elif x.tok == tok.LBRACKET:
- startpos = x.startpos
+ start_offset = x.start_offset
items = []
end_comma = None
if t.peek().tok != tok.RBRACKET:
@@ -83,18 +83,18 @@
# Expect a comma and use it if the value was missing.
x = t.expect(tok.COMMA)
comma = ParseNode(kind.COMMA, None,
- x.startpos, x.endpos, None, [])
+ x.start_offset, x.end_offset, None, [])
items[-1] = items[-1] or comma
# Check for the end.
if t.peek().tok == tok.RBRACKET:
end_comma = comma
break
- endpos = t.expect(tok.RBRACKET).endpos
- return ParseNode(kind.RB, None, startpos, endpos, None, items,
+ end_offset = t.expect(tok.RBRACKET).end_offset
+ return ParseNode(kind.RB, None, start_offset, end_offset, None, items,
end_comma=end_comma)
elif x.tok == tok.LBRACE:
- startpos = x.startpos
+ start_offset = x.start_offset
kids = []
# TODO: get/set
end_comma = None
@@ -104,50 +104,50 @@
break
elif x.tok == tok.STRING:
t.expect(tok.STRING)
- key = ParseNode(kind.STRING, None, x.startpos,
- x.endpos, x.atom, [])
+ key = ParseNode(kind.STRING, None, x.start_offset,
+ x.end_offset, x.atom, [])
elif x.tok == tok.NUMBER:
t.expect(tok.NUMBER)
- key = ParseNode(kind.NUMBER, None, x.startpos,
- x.endpos, x.atom, [])
+ key = ParseNode(kind.NUMBER, None, x.start_offset,
+ x.end_offset, x.atom, [])
else:
x = t.expect_identifiername()
- key = ParseNode(kind.NAME, ...
[truncated message content] |