-
Notifications
You must be signed in to change notification settings - Fork 27
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
- Loading branch information
Showing
5 changed files
with
195 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -462,6 +462,9 @@ | |
}, | ||
"type": "UnusedImport" | ||
}, | ||
{ | ||
"type": "UnusedLocalVar" | ||
}, | ||
{ | ||
"type": "VariableInitialisation" | ||
}, | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
package checkstyle.checks.coding; | ||
|
||
import checkstyle.token.TokenTree; | ||
import checkstyle.utils.StringUtils; | ||
|
||
@name("UnusedLocalVar") | ||
@desc("Checks for unused local variables.") | ||
class UnusedLocalVarCheck extends Check { | ||
|
||
public function new() { | ||
super(TOKEN); | ||
} | ||
|
||
override function actualRun() { | ||
var root:TokenTree = checker.getTokenTree(); | ||
var functions:Array<TokenTree> = root.filter([Kwd(KwdFunction)], ALL); | ||
|
||
for (f in functions) { | ||
if (isPosSuppressed(f.pos)) continue; | ||
var skipFirstFunction:Bool = true; | ||
var localVars:Array<TokenTree> = f.filterCallback(function(tok:TokenTree, depth:Int):FilterResult { | ||
return switch (tok.tok) { | ||
case Kwd(KwdVar): FOUND_SKIP_SUBTREE; | ||
case Kwd(KwdFunction): | ||
if (skipFirstFunction) { | ||
skipFirstFunction = false; | ||
GO_DEEPER; | ||
} | ||
else SKIP_SUBTREE; | ||
default: GO_DEEPER; | ||
} | ||
}); | ||
checkLocalVars(f, localVars); | ||
} | ||
} | ||
|
||
function checkLocalVars(f:TokenTree, localVars:Array<TokenTree>) { | ||
for (localVar in localVars) { | ||
for (child in localVar.childs) { | ||
switch (child.tok) { | ||
case Const(CIdent(name)): | ||
checkLocalVar(f, child, name); | ||
default: | ||
} | ||
} | ||
} | ||
} | ||
|
||
function checkLocalVar(f:TokenTree, v:TokenTree, name:String) { | ||
var ignoreFunctionSignature:Bool = true; | ||
var nameList:Array<TokenTree> = f.filterCallback(function(tok:TokenTree, depth:Int):FilterResult { | ||
if (ignoreFunctionSignature) { | ||
switch (tok.tok) { | ||
case Kwd(KwdPublic), Kwd(KwdPrivate): | ||
return SKIP_SUBTREE; | ||
case At: | ||
return SKIP_SUBTREE; | ||
case Comment(_), CommentLine(_): | ||
return SKIP_SUBTREE; | ||
case POpen: | ||
ignoreFunctionSignature = false; | ||
return SKIP_SUBTREE; | ||
default: | ||
return GO_DEEPER; | ||
} | ||
} | ||
return switch (tok.tok) { | ||
case Const(CIdent(n)): | ||
if (n == name) FOUND_GO_DEEPER; | ||
else GO_DEEPER; | ||
case Const(CString(s)): | ||
checkStringInterpolation(tok, name, s); | ||
default: GO_DEEPER; | ||
} | ||
}); | ||
if (nameList.length > 1) return; | ||
|
||
logPos('Unused local variable $name', v.pos); | ||
} | ||
|
||
function checkStringInterpolation(tok:TokenTree, name:String, s:String):FilterResult { | ||
if (!StringUtils.isStringInterpolation(s, checker.file.content, tok.pos)) { | ||
return GO_DEEPER; | ||
} | ||
|
||
// $name | ||
var format:String = "\\$" + name + "([^_0-9a-zA-Z]|$)"; | ||
var r:EReg = new EReg(format, ""); | ||
if (r.match(s)) { | ||
return FOUND_GO_DEEPER; | ||
} | ||
|
||
// '${name.doSomething()} or ${doSomething(name)} | ||
format = "\\$\\{(|.*[^_0-9a-zA-Z])" + name + "([^_0-9a-zA-Z].*)\\}"; | ||
r = new EReg(format, ""); | ||
if (r.match(s)) { | ||
return FOUND_GO_DEEPER; | ||
} | ||
return GO_DEEPER; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
package checks.coding; | ||
|
||
import checkstyle.checks.coding.UnusedLocalVarCheck; | ||
|
||
class UnusedLocalVarCheckTest extends CheckTestCase<UnusedLocalVarCheckTests> { | ||
|
||
static inline var MSG_UNUSED_VAR_INDEX:String = "Unused local variable index"; | ||
|
||
public function testLocalVar() { | ||
var check = new UnusedLocalVarCheck(); | ||
assertNoMsg(check, USED_INDEX); | ||
assertNoMsg(check, STRING_INTERPOLATION); | ||
} | ||
|
||
public function testUnusedLocalVar() { | ||
var check = new UnusedLocalVarCheck(); | ||
assertMsg(check, UNUSED_INDEX, MSG_UNUSED_VAR_INDEX); | ||
assertMsg(check, UNUSED_INDEX2, MSG_UNUSED_VAR_INDEX); | ||
assertMsg(check, STRING_INTERPOLATION_UNUSED, MSG_UNUSED_VAR_INDEX); | ||
} | ||
} | ||
|
||
@:enum | ||
abstract UnusedLocalVarCheckTests(String) to String { | ||
var USED_INDEX = " | ||
abstractAndClass Test { | ||
function a() { | ||
var index:Int; | ||
index++; | ||
} | ||
@SuppressWarnings('checkstyle:UnusedLocalVar') | ||
function b() { | ||
var index:Int; | ||
} | ||
function c() { | ||
var index:Int; | ||
call(function() { | ||
index++; | ||
}); | ||
} | ||
}"; | ||
|
||
var UNUSED_INDEX = " | ||
abstractAndClass Test { | ||
// index | ||
@index | ||
public function a(index:String) { | ||
var index:Int; | ||
} | ||
}"; | ||
|
||
var UNUSED_INDEX2 = " | ||
abstractAndClass Test { | ||
public function a() { | ||
call(function() { | ||
var index:Int; | ||
}); | ||
} | ||
}"; | ||
|
||
var STRING_INTERPOLATION = " | ||
abstractAndClass Test { | ||
function a() { | ||
var index:Int; | ||
var index2:Array<Int>; | ||
var index3:String; | ||
trace ('$index'); | ||
trace ('${index2.toString()}'); | ||
trace ('${Std.parseInt(index3)}'); | ||
} | ||
}"; | ||
|
||
var STRING_INTERPOLATION_UNUSED = " | ||
abstractAndClass Test { | ||
function a() { | ||
var index:Int; | ||
trace ('index'); | ||
trace ('$index2'); | ||
trace ('${index2.toString()}'); | ||
trace ('${Std.parseInt(index3)}'); | ||
} | ||
}"; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters