我正在编写自定义的棉绒检查以禁止某些方法。因此,如果有人在类foo
的实例上调用了被禁止的方法A
,则皮棉应该报告错误。
我是通过这样的静态方法(在visitCallExpression(UCallExpression)
内部实现的
node.receiver as UReferenceExpression).getQualifiedName()
从限定名称中,我可以获取Class
对象并运行检查,但是对于在实例化对象上调用的方法,我无法获得限定名称。我可以获取对象所属的类的名称,但不能获取限定名称。
如何获取在该类的实例上调用的方法的类的合格名称?如果不清楚,请举一个例子。
import android.view.Button;
class ButtonSetTextIntClass {
private Button button;
public void bannedSetText (){
button.setText(123);
}
}
我需要在visitCallExpression (UCallExpression)
中获得button
的合格名称/类。
答案 0 :(得分:0)
UCallExpression.receiverType
does what you want:
public class CustomDetector extends Detector implements SourceCodeScanner {
@Nullable
@Override
public List<Class<? extends UElement>> getApplicableUastTypes() {
return Collections.singletonList(UCallExpression.class);
}
@Nullable
@Override
public UElementHandler createUastHandler(@NotNull JavaContext context) {
return new UElementHandler() {
@Override
public void visitCallExpression(@NotNull UCallExpression node) {
node.getReceiverType(); // PsiType:Button
}
};
}
}
To extract qualified name you can use the following method:
((PsiClassType) node.getReceiverType()).resolve().getQualifiedName() // android.widget.Button
答案 1 :(得分:0)
我找到了一个适用于静态和非静态方法以及Kotlin顶级功能的解决方案。不确定这是否是最好的方法,但至少能奏效。
override fun visitCallExpression(node: UCallExpression) {
(node.resolve()?.parent as? ClsClassImpl)?.stub?.qualifiedName
}
答案 2 :(得分:0)
/**
* eg: android.util.Log
* ps. imports was initialized in visitImportStatement
*/
private fun getClassNameWithPackage(node: UCallExpression): String {
var className = node.resolve()?.containingClass?.qualifiedName
if (className != null) {
return className
}
className = getClassName(node) ?: return ""
for (import in imports) {
if (import.contains(className)) {
return import
}
}
return "$packageName.$className"
}
/**
* eg: Log
*/
private fun getClassName(node: UCallExpression): String? {
return node.receiver?.javaPsi?.text ?: when (val uExpression = (node.methodIdentifier?.uastParent as UCallExpression?)?.receiver) {
is JavaUSimpleNameReferenceExpression -> {
uExpression.identifier
}
is KotlinUSimpleReferenceExpression -> {
uExpression.identifier
}
is UReferenceExpression -> {
uExpression.getQualifiedName()
}
else -> null
}
}