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