I have a requirement to put some lint checks to warn users to call specific functions (which are non-spending and blocking from a library) to be called from within a suspend function or a coroutine.
I can identify different methods using UCallExpression - overriding visitCallExpressions(). But when there are nested methods and lambdas I cannot identify which is the actual parent - lambda or the containing method.
How to identify immediate parents?
// case 1
fun foo(){
launchl{
val a = object: XYZ {
override fun foobar(): Int {
ABC.testFunc()
}
}
}
}
// case 2
fun foo(){
launchl{
ABC.testFunc()
}
}
// case 3
suspend fun foo() {
ABC.testFunc()
}
Using combinations of the following, I can identify if the testFunc() is inside a coroutine block like launch, async, future, etc. for Case 2 and Case 3:
node = current.getParentType(KotlinUFunctionCallExpression::class.java)
and below to identify methods and class:
(node.receiver as KotlinUQualifiedReferenceExpression).getExpressionType().canonicalText
or
(node.receiver as PsiClassReferenceType).resolve().qualifiedName
or
node.resolve().containingClass.qualifiedName
or
node.methodIdentifier.name
and below code for identifying the suspend function:
current.getParentofType(KotlinUMethod::class.java).modifierList.text
For Case 1, I can use any of the above codes to extract foobar(), launch{} or foo(), but how can I identify which is the first block containing the call ABC.testFunc()? e.g. for Case 1, it should be foobar() and I should WARN using lint to make foobar a suspend or call ABC.testFunc() from inside another coroutine block.