Fix formatting and static code analysis findings.

This commit is contained in:
mitchspano 2024-11-14 23:29:44 +00:00
parent 1a9e721fb6
commit 69a24126f7
2 changed files with 62 additions and 56 deletions

View File

@ -5,82 +5,88 @@
package net.sourceforge.pmd.lang.apex.rule.bestpractices; package net.sourceforge.pmd.lang.apex.rule.bestpractices;
import java.util.List; import java.util.List;
import org.checkerframework.checker.nullness.qual.NonNull;
import net.sourceforge.pmd.lang.apex.ast.ASTMethod; import net.sourceforge.pmd.lang.apex.ast.ASTMethod;
import net.sourceforge.pmd.lang.apex.ast.ASTMethodCallExpression; import net.sourceforge.pmd.lang.apex.ast.ASTMethodCallExpression;
import net.sourceforge.pmd.lang.apex.ast.ASTParameter; import net.sourceforge.pmd.lang.apex.ast.ASTParameter;
import net.sourceforge.pmd.lang.apex.ast.ASTUserClass; import net.sourceforge.pmd.lang.apex.ast.ASTUserClass;
import net.sourceforge.pmd.lang.apex.rule.AbstractApexRule; import net.sourceforge.pmd.lang.apex.rule.AbstractApexRule;
import net.sourceforge.pmd.lang.rule.RuleTargetSelector; import net.sourceforge.pmd.lang.rule.RuleTargetSelector;
import org.checkerframework.checker.nullness.qual.NonNull;
/** /**
* Scans classes which implement the `Queueable` interface. If the `public void * Scans classes which implement the `Queueable` interface. If the `public void
* execute(QueueableContext context)` method does not call the `System.attachFinalizer(Finalizer f)` * execute(QueueableContext context)` method does not call the
* method, then a violation will be added to the `execute` method. * `System.attachFinalizer(Finalizer f)` method, then a violation will be added
* to the `execute` method.
* *
* @author mitchspano * @author mitchspano
*/ */
public class QueueableWithoutFinalizerRule extends AbstractApexRule { public class QueueableWithoutFinalizerRule extends AbstractApexRule {
private static final String EXECUTE = "execute"; private static final String EXECUTE = "execute";
private static final String QUEUEABLE = "queueable"; private static final String QUEUEABLE = "queueable";
private static final String QUEUEABLE_CONTEXT = "queueablecontext"; private static final String QUEUEABLE_CONTEXT = "queueablecontext";
private static final String SYSTEM_ATTACH_FINALIZER = "system.attachfinalizer"; private static final String SYSTEM_ATTACH_FINALIZER = "system.attachfinalizer";
@Override @Override
protected @NonNull RuleTargetSelector buildTargetSelector() { protected @NonNull RuleTargetSelector buildTargetSelector() {
return RuleTargetSelector.forTypes(ASTUserClass.class); return RuleTargetSelector.forTypes(ASTUserClass.class);
} }
/** /**
* If the class implements the `Queueable` interface and the `execute(QueueableContext context)` * If the class implements the `Queueable` interface and the
* does not call the `System.attachFinalizer(Finalizer f)` method, then add a violation. * `execute(QueueableContext context)` does not call the
*/ * `System.attachFinalizer(Finalizer f)` method, then add a violation.
@Override */
public Object visit(ASTUserClass theClass, Object data) { @Override
if (!implementsTheQueueableInterface(theClass)) { public Object visit(ASTUserClass theClass, Object data) {
return data; if (!implementsTheQueueableInterface(theClass)) {
return data;
}
for (ASTMethod theMethod : theClass.descendants(ASTMethod.class).toList()) {
if (isTheExecuteMethodOfTheQueueableInterface(theMethod)
&& !callsTheSystemAttachFinalizerMethod(theMethod)) {
asCtx(data).addViolation(theMethod);
}
}
return data;
} }
for (ASTMethod theMethod : theClass.descendants(ASTMethod.class).toList()) {
if (isTheExecuteMethodOfTheQueueableInterface(theMethod)
&& !callsTheSystemAttachFinalizerMethod(theMethod)) {
asCtx(data).addViolation(theMethod);
}
}
return data;
}
/** Determines if the class implements the Queueable interface. */ /** Determines if the class implements the Queueable interface. */
private boolean implementsTheQueueableInterface(ASTUserClass theClass) { private boolean implementsTheQueueableInterface(ASTUserClass theClass) {
for (String interfaceName : theClass.getInterfaceNames()) { for (String interfaceName : theClass.getInterfaceNames()) {
if (interfaceName.equalsIgnoreCase(QUEUEABLE)) { if (QUEUEABLE.equalsIgnoreCase(interfaceName)) {
return true; return true;
} }
}
return false;
} }
return false;
}
/** /**
* Determines if the method is the `execute(QueueableContext context)` method. Parameter count is * Determines if the method is the `execute(QueueableContext context)`
* checked to account for method overloading. * method. Parameter count is checked to account for method overloading.
*/ */
private boolean isTheExecuteMethodOfTheQueueableInterface(ASTMethod theMethod) { private boolean isTheExecuteMethodOfTheQueueableInterface(ASTMethod theMethod) {
if (!theMethod.getCanonicalName().equalsIgnoreCase(EXECUTE)) { if (!EXECUTE.equalsIgnoreCase(theMethod.getCanonicalName())) {
return false; return false;
}
List<ASTParameter> parameters = theMethod.descendants(ASTParameter.class).toList();
return parameters.size() == 1 && QUEUEABLE_CONTEXT.equalsIgnoreCase(parameters.get(0).getType());
} }
List<ASTParameter> parameters = theMethod.descendants(ASTParameter.class).toList();
return parameters.size() == 1
&& parameters.get(0).getType().equalsIgnoreCase(QUEUEABLE_CONTEXT);
}
/** Determines if the method calls the `System.attachFinalizer(Finalizer f)` method. */ /**
private boolean callsTheSystemAttachFinalizerMethod(ASTMethod theMethod) { * Determines if the method calls the `System.attachFinalizer(Finalizer f)`
for (ASTMethodCallExpression methodCallExpression : * method.
theMethod.descendants(ASTMethodCallExpression.class).toList()) { */
if (methodCallExpression.getFullMethodName().equalsIgnoreCase(SYSTEM_ATTACH_FINALIZER)) { private boolean callsTheSystemAttachFinalizerMethod(ASTMethod theMethod) {
return true; for (ASTMethodCallExpression methodCallExpression : theMethod.descendants(ASTMethodCallExpression.class)
} .toList()) {
if (SYSTEM_ATTACH_FINALIZER.equalsIgnoreCase(methodCallExpression.getFullMethodName())) {
return true;
}
}
return false;
} }
return false;
}
} }

View File

@ -7,5 +7,5 @@ package net.sourceforge.pmd.lang.apex.rule.bestpractices;
import net.sourceforge.pmd.test.PmdRuleTst; import net.sourceforge.pmd.test.PmdRuleTst;
class QueueableWithoutFinalizerTest extends PmdRuleTst { class QueueableWithoutFinalizerTest extends PmdRuleTst {
// no additional unit tests // no additional unit tests
} }