ClassScanner表示需要进行class级别的代码扫描,所以文件都会经过编译成字节码后再进行lint扫描,本文基于CHECK WITH LINT总结使用ClassScanner扫描的过程与技巧。
上文就是使用ClassScanner来进行执行的,ClassScanner的接口定义如下:
1 | public interface ClassScanner { |
List<String> getApplicableCallNames();
List<String> getApplicableCallOwners();
两个方法其实类似,不过一个是用于选择需要捕获的方法名,一个是捕获方法的所属类,如我们需要在当MainActivity作为owners时触发的检查,则可以如下:
1 | public List<String> getApplicableCallOwners() { |
也是class的全路径名,如此就会在checkCall中触发。
checkCall的参数意义上文已经解析过一次,这里再将解释一次。
ClassContext可以认为是被捕捉到的方法所在的类的上下文环境,包括ClassNode,类文件的二进制数据,获取位置(以Node为参)等方法都可以通过上下文获取到,也可以使用其提供的report来报告错误。
ClassNode:这是一个class的节点(node),是ClassVisitor的子类,这个节点里描述了当前类的一些细节,包括接口有哪些,方法有哪些,成员有哪些,甚至内部类有哪些,用于获取类的状态;
MethodNode: 方法的节点对象,是MethodVisitor的子类,跟ClassVisitor类似,同样也是用于描述状态的,里面包含了方法的一些描述,包括权限,方法签名,注解等;
MethodInsnNode: 底层二进制执行(bytecode instruction)的节点,用于描述执行这个方法时的调用细节,每一个方法的执行都对应一个MethodInsnNode,MethodNode表示的是方法的静态状态,而MethodInsnNode描述的是执行过程(instruction)中的状态,如是谁去调用这个方法的,着重运行时;
如此分析的话,其他三个方法也就不难理解。
ClassScanner解析的是类字节码,得到的是编译后的信息,与我们平时反射类似,它能获取到编译进字节码中以及运行时的状态,但对于检查方法中传了什么参数,好像就无能为力,至少我是不知道怎么操作,残念。