-
Notifications
You must be signed in to change notification settings - Fork 84
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #73 from justinmclean/argchecker
Added rule to check for missing function argument types and any types.
- Loading branch information
Showing
2 changed files
with
160 additions
and
0 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 |
---|---|---|
@@ -0,0 +1,65 @@ | ||
package com.cflint.plugins.core; | ||
|
||
import net.htmlparser.jericho.Element; | ||
import cfml.parsing.cfscript.script.CFFuncDeclStatement; | ||
import cfml.parsing.cfscript.script.CFFunctionParameter; | ||
import cfml.parsing.cfscript.script.CFScriptStatement; | ||
|
||
import com.cflint.BugInfo; | ||
import com.cflint.BugList; | ||
import com.cflint.plugins.CFLintScannerAdapter; | ||
import com.cflint.plugins.Context; | ||
import com.cflint.tools.CFTool; | ||
|
||
public class ArgTypeChecker extends CFLintScannerAdapter { | ||
final String severity = "WARNING"; | ||
|
||
@Override | ||
public void expression(final CFScriptStatement expression, final Context context, final BugList bugs) { | ||
if (expression instanceof CFFuncDeclStatement) { | ||
final CFFuncDeclStatement function = (CFFuncDeclStatement) expression; | ||
final int begLine = function.getLine(); | ||
|
||
for (final CFFunctionParameter argument : function.getFormals()) { | ||
final String name = argument.getName(); | ||
final String variableType = argument.getType(); | ||
|
||
if (variableType == null) { | ||
bugs.add(new BugInfo.BugInfoBuilder().setLine(begLine).setMessageCode("ARG_TYPE_MISSING") | ||
.setSeverity(severity).setFilename(context.getFilename()) | ||
.setMessage("Argument " + name + " is missing a type.") | ||
.build()); | ||
} | ||
else if (variableType.equals("any")) { | ||
bugs.add(new BugInfo.BugInfoBuilder().setLine(begLine).setMessageCode("ARG_TYPE_ANY") | ||
.setSeverity(severity).setFilename(context.getFilename()) | ||
.setMessage("Argument " + name + " is any. Please change to be the correct type.") | ||
.build()); | ||
} | ||
} | ||
} | ||
} | ||
|
||
@Override | ||
public void element(final Element element, final Context context, final BugList bugs) { | ||
if (element.getName().equals("cfargument")) { | ||
final String name = element.getAttributeValue("name"); | ||
final String variableType = element.getAttributeValue("type"); | ||
int begLine = element.getSource().getRow(element.getBegin()); | ||
|
||
if (variableType == null) { | ||
bugs.add(new BugInfo.BugInfoBuilder().setLine(begLine).setMessageCode("ARG_TYPE_MISSING") | ||
.setSeverity(severity).setFilename(context.getFilename()) | ||
.setMessage("Argument " + name + " is missing a type.") | ||
.build()); | ||
} | ||
else if (variableType.equals("any")) { | ||
bugs.add(new BugInfo.BugInfoBuilder().setLine(begLine).setMessageCode("ARG_TYPE_ANY") | ||
.setSeverity(severity).setFilename(context.getFilename()) | ||
.setMessage("Argument " + name + " is any. Please change to be the correct type.") | ||
.build()); | ||
} | ||
} | ||
} | ||
|
||
} |
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,95 @@ | ||
package com.cflint; | ||
|
||
import static org.junit.Assert.assertEquals; | ||
|
||
import java.io.IOException; | ||
import java.util.List; | ||
import java.util.Map; | ||
|
||
import org.junit.Before; | ||
import org.junit.Test; | ||
|
||
import cfml.parsing.reporting.ParseException; | ||
|
||
import com.cflint.config.CFLintPluginInfo.PluginInfoRule; | ||
import com.cflint.config.CFLintPluginInfo.PluginInfoRule.PluginMessage; | ||
import com.cflint.config.ConfigRuntime; | ||
import com.cflint.plugins.core.ArgTypeChecker; | ||
|
||
public class TestCFBugs_ArgsType { | ||
|
||
private CFLint cfBugs; | ||
|
||
@Before | ||
public void setUp() { | ||
final ConfigRuntime conf = new ConfigRuntime(); | ||
final PluginInfoRule pluginRule = new PluginInfoRule(); | ||
pluginRule.setName("ArgTypeChecker"); | ||
conf.getRules().add(pluginRule); | ||
final PluginMessage pluginMessageMissing = new PluginMessage("ARG_TYPE_MISSING"); | ||
pluginMessageMissing.setSeverity("WARNING"); | ||
pluginMessageMissing.setMessageText("Argument ${variable} is missing a hint."); | ||
pluginRule.getMessages().add(pluginMessageMissing); | ||
final PluginMessage pluginMessageAny = new PluginMessage("ARG_TYPE_ANY"); | ||
pluginMessageAny.setSeverity("INFO"); | ||
pluginMessageAny.setMessageText("Argument ${variable} is any, please use correct type."); | ||
pluginRule.getMessages().add(pluginMessageAny); | ||
|
||
cfBugs = new CFLint(conf, new ArgTypeChecker()); | ||
} | ||
|
||
@Test | ||
public void testMissingType() throws ParseException, IOException { | ||
final String cfcSrc = "<cfcomponent>\r\n" | ||
+ "<cffunction name=\"test\" returnType=\"void\">\r\n" | ||
+ " <cfargument name=\"xyz\" default=\"123\">\r\n" | ||
+ "</cffunction>\r\n" | ||
+ "</cfcomponent>\r\n"; | ||
cfBugs.process(cfcSrc, "test"); | ||
final List<BugInfo> result = cfBugs.getBugs().getBugList().values().iterator().next(); | ||
assertEquals(1, result.size()); | ||
assertEquals("ARG_TYPE_MISSING", result.get(0).getMessageCode()); | ||
assertEquals(3, result.get(0).getLine()); | ||
} | ||
|
||
@Test | ||
public void testMissingTypeNoTags() throws ParseException, IOException { | ||
final String cfcSrc = "component {\r\n" | ||
+ "public void function test(arg1) {\r\n" | ||
+ "}\r\n" | ||
+ "}\r\n"; | ||
cfBugs.process(cfcSrc, "test"); | ||
final List<BugInfo> result = cfBugs.getBugs().getBugList().values().iterator().next(); | ||
assertEquals(1, result.size()); | ||
assertEquals("ARG_TYPE_MISSING", result.get(0).getMessageCode()); | ||
assertEquals(2, result.get(0).getLine()); | ||
} | ||
|
||
@Test | ||
public void testTypeAny() throws ParseException, IOException { | ||
final String cfcSrc = "<cfcomponent>\r\n" | ||
+ "<cffunction name=\"test\" returnType=\"void\">\r\n" | ||
+ " <cfargument name=\"xyz\" default=\"123\" type=\"any\">\r\n" | ||
+ "</cffunction>\r\n" | ||
+ "</cfcomponent>\r\n"; | ||
cfBugs.process(cfcSrc, "test"); | ||
final List<BugInfo> result = cfBugs.getBugs().getBugList().values().iterator().next(); | ||
assertEquals(1, result.size()); | ||
assertEquals("ARG_TYPE_ANY", result.get(0).getMessageCode()); | ||
assertEquals(3, result.get(0).getLine()); | ||
} | ||
|
||
@Test | ||
public void testTypeAnyNoTags() throws ParseException, IOException { | ||
final String cfcSrc = "component {\r\n" | ||
+ "public void function test(any arg1, numeric arg2) {\r\n" | ||
+ "}\r\n" | ||
+ "}\r\n"; | ||
cfBugs.process(cfcSrc, "test"); | ||
final List<BugInfo> result = cfBugs.getBugs().getBugList().values().iterator().next(); | ||
assertEquals(1, result.size()); | ||
assertEquals("ARG_TYPE_ANY", result.get(0).getMessageCode()); | ||
assertEquals(2, result.get(0).getLine()); | ||
} | ||
|
||
} |