您可以使用ASM来检查该参数是否被使用。
要使用例如 Apache Ivy 将其添加到您的项目中,您可以将其添加到ivy.xml
:
<dependency org="org.ow2.asm" name="asm" rev="6.1.1" />
或者对 Maven、Gradle 等执行等效操作。然后您可以通过以下方式检查参数:
import java.io.IOException;
import java.io.InputStream;
import java.io.UncheckedIOException;
import java.util.concurrent.atomic.AtomicBoolean;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
// . . .
public static boolean usesP2(Evaluator evaluator) {
AtomicBoolean usesP2 = new AtomicBoolean(false);
String internalName = evaluator.getClass().getName().replace('.', '/');
String classFileResource = "/" + internalName + ".class";
ClassVisitor visitor = new ClassVisitor(Opcodes.ASM6) {
@Override
public MethodVisitor visitMethod(int access, String name,
String desc, String signature, String[] exceptions) {
if ("evaluate".equals(name)) {
return new MethodVisitor(Opcodes.ASM6) {
@Override
public void visitVarInsn(final int insn, final int slot) {
if (slot == 2) usesP2.set(true);
}
};
}
return super.visitMethod(access, name, desc, signature, exceptions);
}
};
try (InputStream is = Evaluator.class.getResourceAsStream(classFileResource)) {
ClassReader reader = new ClassReader(is);
reader.accept(visitor, 0);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
return usesP2.get();
}
public static void assertCorrectlyDocumentsP2(Evaluator evaluator) {
boolean usesP2 = usesP2(evaluator);
if (usesP2 && !evaluator.requiresP2()) {
throw new AssertionError(evaluator.getClass().getName() +
" uses P2 without documenting it");
}
if (!usesP2 && evaluator.requiresP2()) {
throw new AssertionError(evaluator.getClass().getName() +
" says it uses P2 but does not");
}
}
单元测试:
@Test
public void testFalsePositive() {
assertCorrectlyDocumentsP2(new FalsePositive());
}
@Test
public static void testFalseNegative() {
assertCorrectlyDocumentsP2(new FalseNegative());
}
(这假设有两个 bad Evaluator
sFalsePositive
和FalseNegative
,其中一个记录了它使用 P2 但没有,另一个没有记录它使用 P2 即使它使用了,分别。)
注意:usesP2
我们在堆栈帧的插槽 2 中检查变量指令(访问局部变量的指令)。插槽从 0 开始编号,第一个是this
. P2 位于插槽 2 中只是因为Evaluator::evaluate
它是一个实例方法。如果它是静态方法,我们必须检查是否使用了slot 1以检测是否使用了参数 P2。警告讲师。