Skip to content

Commit

Permalink
check for variable reuse in nested for loops
Browse files Browse the repository at this point in the history
  • Loading branch information
shamer committed Oct 23, 2015
1 parent b98629d commit 7b9c294
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 1 deletion.
4 changes: 3 additions & 1 deletion closure_linter/error_check.py
Expand Up @@ -37,6 +37,7 @@ class Rule(object):
VARIABLE_ARG_MARKER = 'variable_arg_marker'
UNUSED_PRIVATE_MEMBERS = 'unused_private_members'
UNUSED_LOCAL_VARIABLES = 'unused_local_variables'
REUSED_LOOP_VARIABLE = 'reused_loop_variable'

# Rule to raise all known errors.
ALL = 'all'
Expand All @@ -49,7 +50,8 @@ class Rule(object):
NO_BRACES_AROUND_INHERIT_DOC,
BRACES_AROUND_TYPE,
OPTIONAL_TYPE_MARKER,
VARIABLE_ARG_MARKER])
VARIABLE_ARG_MARKER,
REUSED_LOOP_VARIABLE])


flags.DEFINE_boolean('strict', False,
Expand Down
2 changes: 2 additions & 0 deletions closure_linter/errors.py
Expand Up @@ -139,6 +139,8 @@ def ByName(name):
REMOVE_COMMENT_BEFORE_SUBMIT = 1254
# End of list of ActionScript specific errors.

REUSED_LOOP_VARIABLE = 5000

NEW_ERRORS = frozenset([
# Errors added after 2.0.2:
WRONG_INDENTATION,
Expand Down
1 change: 1 addition & 0 deletions closure_linter/full_test.py
Expand Up @@ -61,6 +61,7 @@
'jsdoc.js',
'limited_doc_checks.js',
'minimal.js',
'nested_loops.js',
'other.js',
'provide_blank.js',
'provide_extra.js',
Expand Down
57 changes: 57 additions & 0 deletions closure_linter/javascriptlintrules.py
Expand Up @@ -80,6 +80,9 @@ def CheckToken(self, token, state):
if error_check.ShouldCheck(Rule.UNUSED_LOCAL_VARIABLES):
self._CheckUnusedLocalVariables(token, state)

if error_check.ShouldCheck(Rule.REUSED_LOOP_VARIABLE):
self._CheckReusedLoopVariable(token, state)

if error_check.ShouldCheck(Rule.UNUSED_PRIVATE_MEMBERS):
# Find all assignments to private members.
if token.type == Type.SIMPLE_LVALUE:
Expand Down Expand Up @@ -597,6 +600,60 @@ def _MarkLocalVariableUsed(self, identifier):
del unused_local_variables[identifier]
break

def _CheckReusedLoopVariable(self, token, state):
"""Checks for reused variables in for loops.
Args:
token: The token to check.
state: The state tracker.
"""
def forLoopVarIdentifier(start_token):
""" returns the identifier for the var declaration, None if it is not present. """
var_token = tokenutil.CustomSearch(
start_token,
lambda t: t.IsKeyword('var'),
end_func=lambda t: t.type == Type.SEMICOLON,
distance=None)
if var_token:
ident_token = tokenutil.CustomSearch(
var_token,
lambda t: t.type == Type.SIMPLE_LVALUE,
end_func=lambda t: t.type == Type.SEMICOLON,
distance=None)
if ident_token:
var_ident = ident_token.string
return var_ident
return None

if token.IsKeyword('for'):
var_ident = forLoopVarIdentifier(token)

block_token = tokenutil.CustomSearch(
token,
lambda t: t.type == Type.START_BLOCK,
end_func=lambda t: t.type == Type.END_BLOCK,
distance=None)
block_counter = 1

# check nested for loops for their variable declarations
if block_token:
next_token = block_token.next
while block_counter:
if next_token.IsKeyword('for'):
inner_var_ident = forLoopVarIdentifier(next_token)
if inner_var_ident and inner_var_ident == var_ident:
reused_loop_ident_msg = 'Reused loop variable %s' % (var_ident, )
self._HandleError(
errors.REUSED_LOOP_VARIABLE,
reused_loop_ident_msg,
token, position=Position.AtBeginning())
elif next_token.type == Type.START_BLOCK:
block_counter += 1
elif next_token.type == Type.END_BLOCK:
block_counter -= 1
next_token = next_token.next


def _ReportMissingProvides(self, missing_provides, token, need_blank_line):
"""Reports missing provide statements to the error handler.
Expand Down
27 changes: 27 additions & 0 deletions closure_linter/testdata/nested_loops.js
@@ -0,0 +1,27 @@

// Reuse of i
for (var i = 0; i < 10; i++) {
for (var i = 3; i < 5; i++) {
}
}


// Reuse of j
for (var j = 10; j < 50; j++) {
for (var q = 0; q < 20; q++) {
for (var j = 7; j < 10; j++) {

}
}
}

// Reuse of r
for (var q = 10; q < 50; q++) {
for (var r = 0; r < 20; r++) {
for (var r = 7; r < 10; r++) {

}
}
}


0 comments on commit 7b9c294

Please sign in to comment.