android - 在 Kotlin 中,我可以将 lint 应用于继承我指定的类的所有类的构造函数吗?

标签 android kotlin lint

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/

相关文章:

android - 无法使用 ADT eclipse 在图形布局中打开 Android 布局 xml 文件

android - 如何在 Android onClick 函数中设置延迟

spring-boot - 如何并行调用多个Spring Webclient并等待结果?

android - makeSceneTransitionAnimation 在使用 AndroidX 时显示错误

python - 在 Python 代码中标记 "print"语句

java - -Xlint :all and maven 有问题

java - Gson java.lang.IllegalArgumentException : No time zone indicator

android - 如何在 android 中制作 "contains"以忽略字母的大写?

kotlin - 验证数据类参数 Kotlin

android - Long.compare 可在 Android<API19 上运行,尽管文档说它不应该