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. |