Thread: [javascriptlint-commit] SF.net SVN: javascriptlint:[357] trunk/javascriptlint/lint.py
Status: Beta
Brought to you by:
matthiasmiller
|
From: <mat...@us...> - 2016-12-23 21:29:46
|
Revision: 357
http://sourceforge.net/p/javascriptlint/code/357
Author: matthiasmiller
Date: 2016-12-23 21:29:43 +0000 (Fri, 23 Dec 2016)
Log Message:
-----------
Refactoring the scope object.
Modified Paths:
--------------
trunk/javascriptlint/lint.py
Modified: trunk/javascriptlint/lint.py
===================================================================
--- trunk/javascriptlint/lint.py 2016-12-23 20:47:15 UTC (rev 356)
+++ trunk/javascriptlint/lint.py 2016-12-23 21:29:43 UTC (rev 357)
@@ -76,54 +76,61 @@
parms = control_comment[len(keyword):].strip()
return (comment, keyword, parms.strip())
-class Scope:
+class ScopeObject:
""" Outer-level scopes will never be associated with a node.
Inner-level scopes will always be associated with a node.
"""
- def __init__(self):
- self._parent = None
+ def __init__(self, parent, node, type_):
+ assert type_ in ('scope', 'arg', 'function', 'var'), \
+ 'Unrecognized identifier type: %s' % type_
+ self._parent = parent
+ self._node = node
+ self._type = type_
self._kids = []
self._identifiers = {}
self._references = []
self._unused = []
- self._node = None
+
+ @property
+ def parent_scope(self):
+ return self._parent
+
+ @property
+ def node(self):
+ return self._node
+
def add_scope(self, node):
assert not node is None
- self._kids.append(Scope())
+ self._kids.append(ScopeObject(self, node, 'scope'))
self._kids[-1]._parent = self
self._kids[-1]._node = node
return self._kids[-1]
+
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_
- }
+ self._identifiers[name] = ScopeObject(self, node, type_)
+
def add_reference(self, name, node):
self._references.append((name, node))
+
def set_unused(self, name, node):
self._unused.append((name, node))
- def get_identifier(self, name):
+
+ def has_property(self, name):
+ return name in self._identifiers
+
+ def get_property_type(self, name):
if name in self._identifiers:
- return self._identifiers[name]['node']
+ return self._identifiers[name]._type
else:
return None
- def get_identifier_type(self, name):
+ def resolve_property(self, name):
if name in self._identifiers:
- return self._identifiers[name]['type']
- else:
- return None
- def get_identifiers(self):
- "returns a list of names"
- return self._identifiers.keys()
- def resolve_identifier(self, name):
- if name in self._identifiers:
- return self, self._identifiers[name]['node']
+ return self._identifiers[name]
if self._parent:
- return self._parent.resolve_identifier(name)
+ return self._parent.resolve_property(name)
return None
+
def get_identifier_warnings(self):
""" Returns a tuple of unreferenced and undeclared, where each is a list
of (scope, name, node) tuples.
@@ -147,6 +154,7 @@
'undeclared': undeclared,
'obstructive': obstructive,
}
+
def _find_warnings(self, unreferenced, undeclared, obstructive,
is_in_with_scope):
""" unreferenced is a dictionary, such that:
@@ -166,25 +174,25 @@
# them if they are referenced. Variables need to be keyed by name
# instead of node, because function parameters share the same node.
for name, info in self._identifiers.items():
- unreferenced[(self, name)] = info['node']
+ unreferenced[(self, name)] = info.node
# Check for variables that hide an identifier in a parent scope.
if self._parent:
for name, info in self._identifiers.items():
- if self._parent.resolve_identifier(name):
- obstructive.append((self, name, info['node']))
+ if self._parent.resolve_property(name):
+ obstructive.append((self, name, info.node))
# Remove all declared variables from the "unreferenced" set; add all
# undeclared variables to the "undeclared" list.
for name, node in self._references:
- resolved = self.resolve_identifier(name)
+ resolved = self.resolve_property(name)
if resolved:
# Make sure this isn't an assignment.
if node.parent.kind in (tok.ASSIGN, tok.INC, tok.DEC) and \
node.node_index == 0 and \
node.parent.parent.kind == tok.SEMI:
continue
- unreferenced.pop((resolved[0], name), None)
+ unreferenced.pop((resolved.parent_scope, name), None)
else:
# with statements cannot have undeclared identifiers.
if not is_in_with_scope:
@@ -192,9 +200,9 @@
# Remove all variables that have been set as "unused".
for name, node in self._unused:
- resolved = self.resolve_identifier(name)
+ resolved = self.resolve_property(name)
if resolved:
- unreferenced.pop((resolved[0], name), None)
+ unreferenced.pop((resolved.parent_scope, name), None)
else:
undeclared.append((self, name, node))
@@ -221,7 +229,7 @@
class _Script:
def __init__(self):
self._imports = set()
- self.scope = Scope()
+ self.scope = ScopeObject(None, None, 'scope')
def importscript(self, script):
self._imports.add(script)
def hasglobal(self, name):
@@ -233,7 +241,7 @@
return
# Check this scope.
- if self.scope.get_identifier(name):
+ if self.scope.has_property(name):
return self
searched.add(self)
@@ -554,7 +562,7 @@
for ref_scope, name, node in identifier_warnings['unreferenced']:
# Ignore the outer scope.
if ref_scope != scope:
- type_ = ref_scope.get_identifier_type(name)
+ type_ = ref_scope.get_property_type(name)
if type_ == 'arg':
report_lint(node, 'unreferenced_argument', name=name)
elif type_ == 'function':
@@ -582,11 +590,11 @@
return onpush
def _warn_or_declare(scope, name, type_, node, report):
- parent_scope, other = scope.resolve_identifier(name) or (None, None)
- if other and parent_scope == scope:
+ property = scope.resolve_property(name)
+ if property and property.parent_scope == scope:
# Only warn about duplications in this scope.
# Other scopes will be checked later.
- if other.kind == tok.NAME and other.opcode == op.ARGNAME:
+ if property.node.kind == tok.NAME and property.node.opcode == op.ARGNAME:
report(node, 'var_hides_arg', name=name)
else:
report(node, 'redeclared_var', name=name)
@@ -617,7 +625,7 @@
_warn_or_declare(scopes[-1], node.fn_name, 'function', node, report)
self._push_scope(node)
for var_name in node.fn_args:
- if scopes[-1].get_identifier(var_name.atom):
+ if scopes[-1].has_property(var_name.atom):
report(var_name, 'duplicate_formal', name=var_name.atom)
scopes[-1].add_declaration(var_name.atom, var_name, 'arg')
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mat...@us...> - 2016-12-23 21:56:39
|
Revision: 358
http://sourceforge.net/p/javascriptlint/code/358
Author: matthiasmiller
Date: 2016-12-23 21:56:37 +0000 (Fri, 23 Dec 2016)
Log Message:
-----------
Remove unused code.
Modified Paths:
--------------
trunk/javascriptlint/lint.py
Modified: trunk/javascriptlint/lint.py
===================================================================
--- trunk/javascriptlint/lint.py 2016-12-23 21:29:43 UTC (rev 357)
+++ trunk/javascriptlint/lint.py 2016-12-23 21:56:37 UTC (rev 358)
@@ -15,12 +15,6 @@
from jsengine.parser import kind as tok
from jsengine.parser import op
-_newline_kinds = (
- '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',
'isNaN', 'isFinite', 'parseFloat', 'parseInt',
@@ -33,19 +27,6 @@
'arguments', 'undefined'
])
-def _find_function(node):
- while node and node.kind != tok.FUNCTION:
- node = node.parent
- return node
-
-def _find_functions(node):
- functions = []
- while node:
- if node.kind == tok.FUNCTION:
- functions.append(node)
- node = node.parent
- return functions
-
def _parse_control_comment(comment):
""" Returns None or (keyword, parms) """
comment_atom = comment.atom.strip()
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mat...@us...> - 2016-12-23 23:22:17
|
Revision: 361
http://sourceforge.net/p/javascriptlint/code/361
Author: matthiasmiller
Date: 2016-12-23 23:22:15 +0000 (Fri, 23 Dec 2016)
Log Message:
-----------
Clarify report_native vs. report_lint.
Modified Paths:
--------------
trunk/javascriptlint/lint.py
Modified: trunk/javascriptlint/lint.py
===================================================================
--- trunk/javascriptlint/lint.py 2016-12-23 22:31:12 UTC (rev 360)
+++ trunk/javascriptlint/lint.py 2016-12-23 23:22:15 UTC (rev 361)
@@ -328,7 +328,7 @@
lint_file(path, 'js', None, encoding)
def _lint_script_part(script_offset, jsversion, script, script_cache, conf,
- ignores, report_native, report_lint, import_callback):
+ ignores, report_parse_error, report_lint, import_callback):
def parse_error(offset, msg, msg_args):
if not msg in ('anon_no_return_value', 'no_return_value',
'redeclared_var', 'var_hides_arg'):
@@ -401,7 +401,7 @@
if not root:
# Report errors and quit.
for offset, msg, msg_args in parse_errors:
- report_native(offset, msg, msg_args)
+ report_parse_error(offset, msg, msg_args)
return
comments = jsparse.filtercomments(possible_comments, root)
@@ -465,7 +465,7 @@
# Wait to report parse errors until loading jsl:ignore directives.
for offset, msg in parse_errors:
- report_native(offset, msg)
+ report_parse_error(offset, msg)
# Find all visitors and convert them into "onpush" callbacks that call "report"
visitors = {
@@ -503,21 +503,17 @@
def _lint_script_parts(script_parts, script_cache, lint_error, conf, import_callback):
def report_lint(node, errname, offset=0, **errargs):
- errdesc = lintwarnings.format_error(errname, **errargs)
- _report(offset or node.start_offset, errname, errdesc, True)
+ assert errname in lintwarnings.warnings, errname
+ if conf[errname]:
+ _report(offset or node.start_offset, errname, errargs)
- def report_native(offset, errname, errargs):
+ def report_parse_error(offset, errname, errargs):
+ assert errname in lintwarnings.errors, errname
+ _report(offset, errname, errargs)
+
+ def _report(offset, errname, errargs):
errdesc = lintwarnings.format_error(errname, **errargs)
- _report(offset, errname, errdesc, False)
- def _report(offset, errname, errdesc, require_key):
- try:
- if not conf[errname]:
- return
- except KeyError, err:
- if require_key:
- raise
-
for start, end in ignores:
if offset >= start and offset <= end:
return
@@ -527,7 +523,7 @@
for script_offset, jsversion, script in script_parts:
ignores = []
_lint_script_part(script_offset, jsversion, script, script_cache, conf, ignores,
- report_native, report_lint, import_callback)
+ report_parse_error, report_lint, import_callback)
scope = script_cache.scope
identifier_warnings = scope.get_identifier_warnings()
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mat...@us...> - 2016-12-23 23:35:43
|
Revision: 362
http://sourceforge.net/p/javascriptlint/code/362
Author: matthiasmiller
Date: 2016-12-23 23:35:40 +0000 (Fri, 23 Dec 2016)
Log Message:
-----------
Centralize ignores and error reporting.
Modified Paths:
--------------
trunk/javascriptlint/lint.py
Modified: trunk/javascriptlint/lint.py
===================================================================
--- trunk/javascriptlint/lint.py 2016-12-23 23:22:15 UTC (rev 361)
+++ trunk/javascriptlint/lint.py 2016-12-23 23:35:40 UTC (rev 362)
@@ -209,6 +209,14 @@
def __init__(self):
self._imports = set()
self.scope = ScopeObject(None, None, 'scope')
+ self._ignores = []
+ def add_ignore(self, start, end):
+ self._ignores.append((start, end))
+ def should_ignore(self, offset):
+ for start, end in self._ignores:
+ if offset >= start and offset <= end:
+ return True
+ return False
def importscript(self, script):
self._imports.add(script)
def hasglobal(self, name):
@@ -276,7 +284,20 @@
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(offset, errname, errdesc):
+
+ def report_lint(node, errname, offset=0, **errargs):
+ assert errname in lintwarnings.warnings, errname
+ if conf[errname]:
+ _report(offset or node.start_offset, errname, errargs)
+
+ def report_parse_error(offset, errname, errargs):
+ assert errname in lintwarnings.errors, errname
+ _report(offset, errname, errargs)
+
+ def _report(offset, errname, errargs):
+ errdesc = lintwarnings.format_error(errname, **errargs)
+ if lint_cache[normpath].should_ignore(offset):
+ return
pos = node_positions.from_offset(offset)
return lint_error(normpath, pos.line, pos.col, errname, errdesc)
@@ -316,7 +337,8 @@
else:
assert False, 'Unsupported file kind: %s' % kind
- _lint_script_parts(script_parts, lint_cache[normpath], _lint_error, conf, import_script)
+ _lint_script_parts(script_parts, lint_cache[normpath], report_lint, report_parse_error,
+ conf, import_script)
return lint_cache[normpath]
lint_cache = {}
@@ -328,7 +350,7 @@
lint_file(path, 'js', None, encoding)
def _lint_script_part(script_offset, jsversion, script, script_cache, conf,
- ignores, report_parse_error, report_lint, import_callback):
+ report_parse_error, report_lint, import_callback):
def parse_error(offset, msg, msg_args):
if not msg in ('anon_no_return_value', 'no_return_value',
'redeclared_var', 'var_hides_arg'):
@@ -432,7 +454,7 @@
start_ignore = node
elif keyword == 'end':
if start_ignore:
- ignores.append((start_ignore.start_offset, node.end_offset))
+ script_cache.add_ignore(start_ignore.start_offset, node.end_offset)
start_ignore = None
else:
report(node, 'mismatch_ctrl_comments')
@@ -501,28 +523,11 @@
for node in jsparse.find_trailing_whitespace(script, script_offset):
report(node, 'trailing_whitespace')
-def _lint_script_parts(script_parts, script_cache, lint_error, conf, import_callback):
- def report_lint(node, errname, offset=0, **errargs):
- assert errname in lintwarnings.warnings, errname
- if conf[errname]:
- _report(offset or node.start_offset, errname, errargs)
+def _lint_script_parts(script_parts, script_cache, report_lint, report_parse_error, conf,
+ import_callback):
- def report_parse_error(offset, errname, errargs):
- assert errname in lintwarnings.errors, errname
- _report(offset, errname, errargs)
-
- def _report(offset, errname, errargs):
- errdesc = lintwarnings.format_error(errname, **errargs)
-
- for start, end in ignores:
- if offset >= start and offset <= end:
- return
-
- return lint_error(offset, errname, errdesc)
-
for script_offset, jsversion, script in script_parts:
- ignores = []
- _lint_script_part(script_offset, jsversion, script, script_cache, conf, ignores,
+ _lint_script_part(script_offset, jsversion, script, script_cache, conf,
report_parse_error, report_lint, import_callback)
scope = script_cache.scope
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mat...@us...> - 2016-12-23 23:38:51
|
Revision: 363
http://sourceforge.net/p/javascriptlint/code/363
Author: matthiasmiller
Date: 2016-12-23 23:38:49 +0000 (Fri, 23 Dec 2016)
Log Message:
-----------
Remove obsolete checks.
Modified Paths:
--------------
trunk/javascriptlint/lint.py
Modified: trunk/javascriptlint/lint.py
===================================================================
--- trunk/javascriptlint/lint.py 2016-12-23 23:35:40 UTC (rev 362)
+++ trunk/javascriptlint/lint.py 2016-12-23 23:38:49 UTC (rev 363)
@@ -352,9 +352,7 @@
def _lint_script_part(script_offset, jsversion, script, script_cache, conf,
report_parse_error, report_lint, import_callback):
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((offset, msg, msg_args))
+ parse_errors.append((offset, msg, msg_args))
def report(node, errname, offset=0, **errargs):
if errname == 'empty_statement' and node.kind == tok.LC:
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mat...@us...> - 2018-01-02 20:28:01
|
Revision: 373
http://sourceforge.net/p/javascriptlint/code/373
Author: matthiasmiller
Date: 2018-01-02 20:28:00 +0000 (Tue, 02 Jan 2018)
Log Message:
-----------
Fix missing parameter in lint_files.
Modified Paths:
--------------
trunk/javascriptlint/lint.py
Modified: trunk/javascriptlint/lint.py
===================================================================
--- trunk/javascriptlint/lint.py 2016-12-30 22:51:46 UTC (rev 372)
+++ trunk/javascriptlint/lint.py 2018-01-02 20:28:00 UTC (rev 373)
@@ -311,7 +311,7 @@
try:
contents = fs.readfile(path, encoding)
except IOError, error:
- lint_error(normpath, 0, 0, 'io_error', unicode(error))
+ lint_error(normpath, 0, 0, 'error', 'io_error', unicode(error))
return lint_cache[normpath]
node_positions = jsparse.NodePositions(contents)
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|