The documentation includes general guidance on adding coding rules, including which languages support adding custom rules, and general guidance on how to go about it.
If the docs don’t answer your question, please tell us:
What language are you writing rules for? Java
What have you tried, and what’s your challenge / stumbling block
Please share the relevant code snippet, along with any error messages you’re encountering:
Also, I don’t think the ArgumentTypes input is looking for an argument list. Instead, I think it expects a simple list of possible argument types. In fact, it’s possible this isn’t working for you because it assumes single-arg methods. But I would first try simplifying that ArgumentTypes value.
java.lang.String, org.json.JSONObject, false is close to what argumentTypes is giving as an example (java.lang.String, int[], int; I assume that means funcA(String foo, int[] bar, int baz))
… ofc false is not a type, but I’d rather not ban true
What I’m saying is that this rule template (technically, we don’t consider this a “custom rule”) may not work, or may not work as you expect with methods that accept multiple arguments.
Can you try clearing out the ArgumentTypes field and just setting it to java.lang.String?
As you mentioned, the rule template cannot match the desired method invocation because false is not a type. Thus, it will never match the method signature you are interested in.
This rule template is not meant to check the values provided to the method’s parameter, but it only checks if a specific method signature is being invoked at any point.
To do what you want you should try with a custom rule.
… Or at least point me “where in documentation” creating a custom rule is “abundantly explained”
As you mentioned, the rule template cannot match the desired method invocation because false is not a type. Thus, it will never match the method signature you are interested in.
I have created that template, but it’s “ghosting me”. It does not complain that it is wrong (or right!), and I don’t know how could I have triggered it. I could try to ban all , boolean invocations of it - but it’s still ignoring me
Here you can find the tutorial on how to bootstrap your first custom plugin, with your own rules.
You could implement the rule you described with the AbstractMethodDetection class and the MethodMatchers API to detect the method you want. I suggest you to go through the tutorial to get an idea of how all this works, but your new rule should look something like this:
@Rule(key = "DisallowJSONAssert_assertEquals")
public class DisallowJSONAssert extends AbstractMethodDetection {
private static final MethodMatchers JSON_ASSERT_MATCHER = MethodMatchers.create()
.ofTypes("org.skyscreamer.jsonassert.JSONAssert")
.names("assertEquals")
.addParametersMatcher("java.lang.String", "java.lang.String", "boolean")
.build();
@Override
protected MethodMatchers getMethodInvocationMatchers() {
return JSON_ASSERT_MATCHER;
}
@Override
protected void onMethodInvocationFound(MethodInvocationTree mit) {
//when this method is invoked it means that the rule matched on a method invocation
//with the signature of JSONAssert.assertEquals(String, String, boolean)
ExpressionTree booleanArg = mit.arguments().get(2);
boolean value = Boolean.parseBoolean(((LiteralTree) booleanArg).value());
//after getting the value of the boolean argument, we can report an issue if it is false
if(!value){
reportIssue(ExpressionUtils.methodName(mit), "Remove this forbidden call");
}
}
}
Whoops, actually you cannot directly use the AbstractMethodDetection as it is not part of the public API, but you can easily look at its implementation to replicate its behavior in a subclass of IssuableSubscriptionVisitor (which is the class you should extend, part of the public API)
DisallowJSONAssert is copy-paste from yours, and AbstractMethodDetection does not matter (since the test runs “locally”, and AbstractMethodDetection is available)
So I think if you can confirm that after adding that entry in the pom.xml file you can see the jsonassert-1.5.1.jar file inside target/test-jars folder, now the last step remaining is to specify this classpath in your unit test, like so: