UCallExpression.resolve分析

简介

在自定义Lint检测Detector时,我们有时候会在override fun createUastHandler(context: JavaContext): UElementHandler?中创建一个自定义的UElementHandler进行后续的检测,它内部定义了非常多的visitXX接口用于访问不同的Element(访问者模式)。

其中,override fun visitCallExpression(node: UCallExpression)可以用来检测所有的代码表达式,如果我们希望将node解析为一个方法时,就需要用到这篇文章的主角了——UCallExpression.resolve()

方法作用

UCallExpression.resolve()返回值为com.intellij.psi.PsiMethod,从它里面我们可以对该方法做大量判断,例如:

  1. PsiType getReturnType():获取返回值类型
  2. PsiReferenceList getThrowsList():获取抛出问题列表
  3. boolean isConstructor():是否是构造方法
  4. PsiMethod[] findSuperMethods():获取super方法
  5. JvmParameter[] getParameters():获取参数
  6. getAnnotations():获取注解
  7. boolean isDeprecated():是否是过时方法

PsiMethod如此强大,如果想做关于方法的检测,基本上只要获取到PsiMethod就可以实现。但是这里有坑了,有时候我们执行node.resolve的结果却是null,这是为什么呢?

resolve==null的几种情况

非全量lint

有时候我们执行lint时是通过LintCliClient.run(LintIssueRegistry, List<File>)方法启动的,这里我们是传入了一个待检测文件列表,Lint只会检查传入的文件。

假设我们传入了一个A类,里面调用了B.b()方法,如果B类没有包含在List中传入LintCliClient的话,b()方法是无法识别的,因为没有B类,LintCliClient也不知道b是什么,所以resolve会是null。

无法识别参数的方法
  1. 与R文件引用有关的方法,例如:
    • setContentView(R.layout.xx)
    • LayoutInflater.inflate(R.layout.xx)
    • Context.getString(R.string.xx)
    • EditText.setHint(R.string.xx)
    • TextView.setText(R.string.xx)
  2. 变长参数方法: A.a(B… bs)
kotlin相关
  1. 使用了别名类TypeAliases.kt提供的ArrayList、HashMap、LinkedHashMap、HashSet、LinkedHashSet进行类构造;
  2. kotlin中使用了java类的构造方法(不限于继承时的构造方法申明)
  3. 使用了ArrayList.isNullOrEmpty()等inline扩展方法
node自身就是null

这个。。确实有这样的情况,但是我暂时没能定位到该node具体是什么,没有找到规律。

结论

通过以上测试,我们发现node.resolve==null的情况大多数都是与环境、android sdk api或者kotlin语言有关,所以对于我们自己代码的检测可以直接忽略这种情况,在Google官方提供的Lint检测库中也是采用了忽略的策略。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值