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