diff --git a/src/main/java/com/cflint/CFLint.java b/src/main/java/com/cflint/CFLint.java index dc78ab1a1..a7c70916c 100644 --- a/src/main/java/com/cflint/CFLint.java +++ b/src/main/java/com/cflint/CFLint.java @@ -303,6 +303,7 @@ public void scan(final File folderOrFile) { } protected void printException(final Exception e, final Element... elem) { + e.printStackTrace(); if (!quiet) { if (elem != null && elem.length > 0 && elem[0] != null) { final int line = elem[0].getSource().getRow(elem[0].getBegin()); @@ -1331,9 +1332,11 @@ public void reportRule(final Element elem, final Object currentExpression, final //A bit of a hack to fix the offset issue //This could be handled better at the source where line and offset are calc'd. int idxOffSet = 1; - if(lineOffsets != null && msg.getLine()!=null && msg.getOffset() != null && msg.getOffset() >=lineOffsets[msg.getLine()] ){ - idxOffSet=0; - } + try{ + if(lineOffsets != null && msg.getLine()!=null && msg.getOffset() != null && msg.getOffset() >=lineOffsets[msg.getLine()] ){ + idxOffSet=0; + } + }catch(ArrayIndexOutOfBoundsException e){} if (expression instanceof CFExpression) { final BugInfo bugInfo = bldr.build((CFExpression) expression, elem); final Token token = ((CFExpression) expression).getToken(); diff --git a/src/main/java/com/cflint/plugins/core/UnusedArgumentChecker.java b/src/main/java/com/cflint/plugins/core/UnusedArgumentChecker.java index 4e2df38ef..a1e285204 100644 --- a/src/main/java/com/cflint/plugins/core/UnusedArgumentChecker.java +++ b/src/main/java/com/cflint/plugins/core/UnusedArgumentChecker.java @@ -3,6 +3,7 @@ import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; +import java.util.Map.Entry; import com.cflint.BugList; import com.cflint.CF; @@ -11,6 +12,7 @@ import cfml.parsing.cfscript.CFExpression; import cfml.parsing.cfscript.CFFullVarExpression; +import cfml.parsing.cfscript.CFFunctionExpression; import cfml.parsing.cfscript.CFIdentifier; import cfml.parsing.cfscript.script.CFFuncDeclStatement; import cfml.parsing.cfscript.script.CFFunctionParameter; @@ -20,22 +22,32 @@ public class UnusedArgumentChecker extends CFLintScannerAdapter { // Use linked hash map to preserve the order of the elements. - protected Map methodArguments = new LinkedHashMap<>(); - protected Map argumentLineNo = new HashMap<>(); - protected Map argumentOffset = new HashMap<>(); - +// protected Map methodArguments = new LinkedHashMap<>(); +// protected Map argumentLineNo = new HashMap<>(); +// protected Map argumentOffset = new HashMap<>(); + protected Map currentArgs = new LinkedHashMap<>(); + + static class ArgInfo{ + Boolean used = false; + Integer argumentLineNo; + Integer argumentOffset; + String type; + } + @Override public void element(final Element element, final Context context, final BugList bugs) { if (element.getName().equals(CF.CFARGUMENT)) { final String name = element.getAttributeValue(CF.NAME) != null ? element.getAttributeValue(CF.NAME).toLowerCase() : ""; - methodArguments.put(name, false); - setArgumentLineNo(name, context.startLine()); - setArgumentOffset(name, element.getAttributeValue(CF.NAME) != null - ? element.getAttributes().get(CF.NAME).getValueSegment().getBegin() : element.getBegin()); + ArgInfo argInfo = new ArgInfo(); + argInfo.argumentLineNo=context.startLine(); + argInfo.argumentOffset=element.getAttributeValue(CF.NAME) != null + ? element.getAttributes().get(CF.NAME).getValueSegment().getBegin() : element.getBegin(); + argInfo.type=element.getAttributeValue(CF.TYPE); + currentArgs.put(name, argInfo); final String code = element.getParentElement().toString(); if (isUsed(code, name)) { - methodArguments.put(name, true); + argInfo.used=true; } } } @@ -47,28 +59,18 @@ public void expression(final CFScriptStatement expression, final Context context for (final CFFunctionParameter argument : function.getFormals()) { final String name = argument.getName().toLowerCase(); // CF variable names are not case sensitive - methodArguments.put(name, false); - setArgumentLineNo(name, function.getLine()); - setArgumentOffset(name, context.offset() + argument.getOffset() ); + ArgInfo argInfo = new ArgInfo(); + argInfo.argumentLineNo=function.getLine(); + argInfo.argumentOffset=context.offset() + argument.getOffset(); + argInfo.type=argument.getType(); + currentArgs.put(name, argInfo); if (isUsed(function.Decompile(0), name)) { - methodArguments.put(name, true); + argInfo.used=true; } } } } - protected void setArgumentLineNo(final String argument, final Integer lineNo) { - if (argumentLineNo.get(argument) == null) { - argumentLineNo.put(argument, lineNo); - } - } - - protected void setArgumentOffset(final String argument, final Integer offset) { - if (argumentOffset.get(argument) == null) { - argumentOffset.put(argument, offset); - } - } - protected void useIdentifier(final CFFullVarExpression fullVarExpression) { if (!fullVarExpression.getExpressions().isEmpty()) { final CFExpression identifier1 = fullVarExpression.getExpressions().get(0); @@ -88,8 +90,15 @@ protected void useIdentifier(final CFFullVarExpression fullVarExpression) { protected void useIdentifier(final CFIdentifier identifier) { final String name = identifier.getName().toLowerCase(); - if (methodArguments.get(name) != null) { - methodArguments.put(name, true); + if (currentArgs.get(name) != null) { + currentArgs.get(name).used=true; + } + } + + protected void useIdentifier(final CFFunctionExpression identifier) { + final String name = identifier.getName().toLowerCase(); + if (currentArgs.get(name) != null && CF.FUNCTION.equalsIgnoreCase(currentArgs.get(name).type)) { + currentArgs.get(name).used=true; } } @@ -99,24 +108,25 @@ public void expression(final CFExpression expression, final Context context, fin useIdentifier((CFFullVarExpression) expression); } else if (expression instanceof CFIdentifier) { useIdentifier((CFIdentifier) expression); + } else if(expression instanceof CFFunctionExpression){ + useIdentifier((CFFunctionExpression) expression); } } @Override public void startFunction(final Context context, final BugList bugs) { - methodArguments.clear(); - argumentLineNo.clear(); + currentArgs.clear(); } @Override public void endFunction(final Context context, final BugList bugs) { // sort by line number - for (final Map.Entry method : methodArguments.entrySet()) { + for (final Entry method : currentArgs.entrySet()) { final String name = method.getKey(); - final Boolean used = method.getValue(); - final int offset = argumentOffset.get(name); - if (!used) { - context.addMessage("UNUSED_METHOD_ARGUMENT", name, argumentLineNo.get(name), offset); + final ArgInfo argInfo = method.getValue(); + final int offset = argInfo.argumentOffset; + if (!argInfo.used) { + context.addMessage("UNUSED_METHOD_ARGUMENT", name, argInfo.argumentLineNo, offset); } } } diff --git a/src/test/resources/com/cflint/tests/UnusedArgument/FunctionArg_550.cfc b/src/test/resources/com/cflint/tests/UnusedArgument/FunctionArg_550.cfc new file mode 100644 index 000000000..a16265bed --- /dev/null +++ b/src/test/resources/com/cflint/tests/UnusedArgument/FunctionArg_550.cfc @@ -0,0 +1,5 @@ +component{ +public string function myFunction(function doSomething){ + return doSomething(); +} +} \ No newline at end of file diff --git a/src/test/resources/com/cflint/tests/UnusedArgument/FunctionArg_550.expected.txt b/src/test/resources/com/cflint/tests/UnusedArgument/FunctionArg_550.expected.txt new file mode 100644 index 000000000..f78a68a48 --- /dev/null +++ b/src/test/resources/com/cflint/tests/UnusedArgument/FunctionArg_550.expected.txt @@ -0,0 +1,11 @@ +{ + "version" : "", + "timestamp" : 1507944141, + "issues" : [ ], + "counts" : { + "totalFiles" : 0, + "totalLines" : 0, + "countByCode" : [ ], + "countBySeverity" : [ ] + } +} \ No newline at end of file