[javascriptlint-commit] SF.net SVN: javascriptlint:[285] trunk
Status: Beta
Brought to you by:
matthiasmiller
|
From: <mat...@us...> - 2009-10-22 13:30:59
|
Revision: 285
http://javascriptlint.svn.sourceforge.net/javascriptlint/?rev=285&view=rev
Author: matthiasmiller
Date: 2009-10-22 13:30:51 +0000 (Thu, 22 Oct 2009)
Log Message:
-----------
1516656: Add warning about identifiers hiding an identifier in a parent scope.
Modified Paths:
--------------
trunk/javascriptlint/jsparse.py
trunk/javascriptlint/lint.py
trunk/javascriptlint/warnings.py
trunk/tests/control_comments/declare.js
trunk/tests/warnings/var_hides_arg.js
Added Paths:
-----------
trunk/tests/warnings/identifier_hides_another.js
Modified: trunk/javascriptlint/jsparse.py
===================================================================
--- trunk/javascriptlint/jsparse.py 2009-10-22 11:52:52 UTC (rev 284)
+++ trunk/javascriptlint/jsparse.py 2009-10-22 13:30:51 UTC (rev 285)
@@ -174,7 +174,7 @@
start_pos = node_positions.from_offset(start_offset)
end_pos = node_positions.from_offset(end_offset)
kwargs = {
- 'type': 'COMMENT',
+ 'kind': 'COMMENT',
'atom': comment_text,
'opcode': opcode,
'_start_line': start_pos.line,
Modified: trunk/javascriptlint/lint.py
===================================================================
--- trunk/javascriptlint/lint.py 2009-10-22 11:52:52 UTC (rev 284)
+++ trunk/javascriptlint/lint.py 2009-10-22 13:30:51 UTC (rev 285)
@@ -117,13 +117,14 @@
if self._parent:
return self._parent.resolve_identifier(name)
return None
- def get_unreferenced_and_undeclared_identifiers(self):
+ def get_identifier_warnings(self):
""" Returns a tuple of unreferenced and undeclared, where each is a list
of (scope, name, node) tuples.
"""
unreferenced = {}
undeclared = []
- self._find_unreferenced_and_undeclared(unreferenced, undeclared, False)
+ obstructive = []
+ self._find_warnings(unreferenced, undeclared, obstructive, False)
# Convert "unreferenced" from a dictionary of:
# { (scope, name): node }
@@ -134,15 +135,22 @@
in unreferenced.items()]
unreferenced.sort(key=lambda x: x[2].start_pos())
- return unreferenced, undeclared
- def _find_unreferenced_and_undeclared(self, unreferenced, undeclared,
- is_in_with_scope):
+ return {
+ 'unreferenced': unreferenced,
+ 'undeclared': undeclared,
+ 'obstructive': obstructive,
+ }
+ def _find_warnings(self, unreferenced, undeclared, obstructive,
+ is_in_with_scope):
""" unreferenced is a dictionary, such that:
(scope, name): node
}
undeclared is a list, such that: [
(scope, name, node)
]
+ obstructive is a list, such that: [
+ (scope, name, node)
+ ]
"""
if self._node and self._node.kind == tok.WITH:
is_in_with_scope = True
@@ -153,6 +161,12 @@
for name, info in self._identifiers.items():
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']))
+
# Remove all declared variables from the "unreferenced" set; add all
# undeclared variables to the "undeclared" list.
for name, node in self._references:
@@ -170,8 +184,8 @@
undeclared.append((self, name, node))
for child in self._kids:
- child._find_unreferenced_and_undeclared(unreferenced, undeclared,
- is_in_with_scope)
+ child._find_warnings(unreferenced, undeclared, obstructive,
+ is_in_with_scope)
def find_scope(self, node):
for kid in self._kids:
scope = kid.find_scope(node)
@@ -432,10 +446,7 @@
for name, node in declares:
declare_scope = script_cache.scope.find_scope(node)
- if declare_scope.get_identifier(name):
- report(node, 'redeclared_var', name=name)
- else:
- declare_scope.add_declaration(name, node, 'var')
+ _warn_or_declare(declare_scope, name, 'var', node, report)
def _lint_script_parts(script_parts, script_cache, lint_error, conf, import_callback):
def report_lint(node, errname, pos=None, **errargs):
@@ -466,15 +477,15 @@
report_native, report_lint, import_callback)
scope = script_cache.scope
- unreferenced, undeclared = scope.get_unreferenced_and_undeclared_identifiers()
- for decl_scope, name, node in undeclared:
+ identifier_warnings = scope.get_identifier_warnings()
+ for decl_scope, name, node in identifier_warnings['undeclared']:
if name in conf['declarations']:
continue
if name in _globals:
continue
if not script_cache.hasglobal(name):
report_lint(node, 'undeclared_identifier', name=name)
- for ref_scope, name, node in unreferenced:
+ for ref_scope, name, node in identifier_warnings['unreferenced']:
# Ignore the outer scope.
if ref_scope != scope:
type_ = ref_scope.get_identifier_type(name)
@@ -486,6 +497,8 @@
report_lint(node, 'unreferenced_variable', name=name)
else:
assert False, 'Unrecognized identifier type: %s' % type_
+ for ref_scope, name, node in identifier_warnings['obstructive']:
+ report_lint(node, 'identifier_hides_another', name=name)
def _getreporter(visitor, report):
def onpush(node):
@@ -504,12 +517,14 @@
def _warn_or_declare(scope, name, type_, node, report):
parent_scope, other = scope.resolve_identifier(name) or (None, None)
- if other and other.kind == tok.FUNCTION and name in other.fn_args:
- report(node, 'var_hides_arg', name=name)
- elif other and parent_scope == scope:
- report(node, 'redeclared_var', name=name)
+ 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:
+ report(node, 'var_hides_arg', name=name)
+ else:
+ report(node, 'redeclared_var', name=name)
else:
- # TODO: Warn when hiding a variable in a parent scope.
scope.add_declaration(name, node, type_)
def _get_scope_checks(scope, report):
Modified: trunk/javascriptlint/warnings.py
===================================================================
--- trunk/javascriptlint/warnings.py 2009-10-22 11:52:52 UTC (rev 284)
+++ trunk/javascriptlint/warnings.py 2009-10-22 13:30:51 UTC (rev 285)
@@ -82,6 +82,7 @@
'nested_comment': 'nested comment',
'legacy_cc_not_understood': 'couldn\'t understand control comment using /*@keyword@*/ syntax',
'var_hides_arg': 'variable {name} hides argument',
+ 'identifier_hides_another': 'identifer {name} hides an identifier in a parent scope',
'duplicate_formal': 'duplicate formal argument {name}',
'missing_semicolon': 'missing semicolon',
'missing_semicolon_for_lambda': 'missing semicolon for lambda assignment',
Modified: trunk/tests/control_comments/declare.js
===================================================================
--- trunk/tests/control_comments/declare.js 2009-10-22 11:52:52 UTC (rev 284)
+++ trunk/tests/control_comments/declare.js 2009-10-22 13:30:51 UTC (rev 285)
@@ -1,4 +1,5 @@
/*jsl:option explicit*/
+/*conf:-identifier_hides_another*/
function declare() {
window.alert('http://www.javascriptlint.com/');
/*jsl:declare window*/ /*warning:redeclared_var*/
Added: trunk/tests/warnings/identifier_hides_another.js
===================================================================
--- trunk/tests/warnings/identifier_hides_another.js (rev 0)
+++ trunk/tests/warnings/identifier_hides_another.js 2009-10-22 13:30:51 UTC (rev 285)
@@ -0,0 +1,43 @@
+// Test each combination of arg, var, function, and jsl:declare.
+function identifier_hides_another(arg_hides_arg,
+ function_hides_arg,
+ var_hides_arg,
+ declare_hides_arg) {
+
+ function arg_hides_function() { return true; }
+ function function_hides_function() { return true; }
+ function var_hides_function() { return true; }
+ function declare_hides_function() { return true; }
+
+ var arg_hides_var;
+ var function_hides_var;
+ var var_hides_var;
+ var declare_hides_var;
+
+ /*jsl:declare arg_hides_declare*/
+ /*jsl:declare function_hides_declare*/
+ /*jsl:declare var_hides_declare*/
+ /*jsl:declare declare_hides_declare*/
+
+ function inner(arg_hides_arg,
+ arg_hides_function,
+ arg_hides_var,
+ arg_hides_declare) { /*warning:identifier_hides_another*//*warning:identifier_hides_another*//*warning:identifier_hides_another*//*warning:identifier_hides_another*/
+
+ function function_hides_arg() { return true; } /*warning:identifier_hides_another*/
+ function function_hides_function() { return true; } /*warning:identifier_hides_another*/
+ function function_hides_var() { return true; } /*warning:identifier_hides_another*/
+ function function_hides_declare() { return true; } /*warning:identifier_hides_another*/
+
+ var var_hides_arg; /*warning:identifier_hides_another*/
+ var var_hides_function; /*warning:identifier_hides_another*/
+ var var_hides_var; /*warning:identifier_hides_another*/
+ var var_hides_declare; /*warning:identifier_hides_another*/
+
+ /*jsl:declare declare_hides_arg*/ /*warning:identifier_hides_another*/
+ /*jsl:declare declare_hides_function*/ /*warning:identifier_hides_another*/
+ /*jsl:declare declare_hides_var*/ /*warning:identifier_hides_another*/
+ /*jsl:declare declare_hides_declare*/ /*warning:identifier_hides_another*/
+ }
+}
+
Property changes on: trunk/tests/warnings/identifier_hides_another.js
___________________________________________________________________
Added: svn:mergeinfo
+
Modified: trunk/tests/warnings/var_hides_arg.js
===================================================================
--- trunk/tests/warnings/var_hides_arg.js 2009-10-22 11:52:52 UTC (rev 284)
+++ trunk/tests/warnings/var_hides_arg.js 2009-10-22 13:30:51 UTC (rev 285)
@@ -2,6 +2,6 @@
function var_hides_arg(duplicate1, duplicate2) {
var duplicate1; /*warning:var_hides_arg*/
function inner() {
- var duplicate2; /*warning:var_hides_arg*/
+ var duplicate2; /*warning:identifier_hides_another*/
}
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|