class SomeDetector : Detector(), SourceCodeScanner {
override fun getApplicableConstructorTypes(): List<String>? {
return listOf(PARENT_CLASS)
}
override fun visitConstructor(context: JavaContext, node: UCallExpression, constructor: PsiMethod) {
// blabla...
}
}
好的,我什至成功地将 lint 应用于每个类的单个构造函数。但是,我要验证数百个类,它们都继承了一个通用接口(interface)。
所以我想验证
all classes inheriting the interface I specified
的构造函数.我要验证的类有一个android依赖,所以像反射这样的库不能直接在lint模块中使用,这是一个java库。
你能帮我满足我的要求吗?
最佳答案
我解决了你的问题。我检查了注释中的值和使用的参数是否相等。您可以调整代码以满足您的要求。这是一个样本Detector
我在其中使用评论提供了解释的类(class)。你可以改进它。
class InvalidConstructorCallDetector : Detector(), Detector.UastScanner {
// Check for call expressions
override fun getApplicableUastTypes() = listOf(UCallExpression::class.java)
override fun createUastHandler(context: JavaContext) = object : UElementHandler() {
override fun visitCallExpression(node: UCallExpression) {
// Check if call is constructor call and if the class referenced inherits your interface
if (node.isConstructorCall() &&
context.doesInherit(node, "com.example.android.YourInterface")
) {
val constructor = node.resolve()!!
// Get the first parameter. You may use a loop and check for all parameter or whatever you require
val param = constructor.parameterList.parameters[0]
// Get your annotation
val paramAnnotation =
param.getAnnotation("com.example.android.YourAnnotation")!!
// Get the value you specified in the annotation for the constructor declaration
val attributeValue = paramAnnotation.findAttributeValue("value")!!.text.toInt()
// Get the argument used for first parameter. Again, you can have this in a loop and use index
val argumentValue = node.getArgumentForParameter(0)!!.evaluate().toString().toInt()
if (attributeValue != argumentValue) // Checking for equality. Perform whatever check you want
{
context.report(
ISSUE,
node,
context.getNameLocation(node),
"Argument value($argumentValue) is invalid. Valid argument: $attributeValue"
)
}
}
}
}
// Check to see if class referenced by constructor call implements interface
private fun JavaContext.doesInherit(node: UCallExpression, typeName: String): Boolean {
for (type in node.classReference!!.getExpressionType()!!.superTypes) {
if (evaluator.typeMatches(type, typeName)) return true
}
return false
}
companion object {
val ISSUE = Issue.create(
"InvalidConstructorCall",
"Invalid arguments in constructor call",
"Only values defined in annotation in constructor declaration are allowed",
Category.CORRECTNESS,
10,
Severity.ERROR,
Implementation(
InvalidConstructorCallDetector::class.java,
EnumSet.of(Scope.JAVA_FILE)
)
)
}
}
关于android - 在 Kotlin 中,我可以将 lint 应用于继承我指定的类的所有类的构造函数吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64058302/