首页 > 解决方案 > 如何检查 kotlin 属性是否在 android lint 中是私有的?

问题描述

我正在编写一个自定义的 android lint 来帮助检查私有属性是否匹配命名约定。

我使用测试用例来验证我的实现。我使用了一种方法isPrivateOrParameterInPrivateMethod()来检查它是否是私有的,但true每次运行它似乎都会返回。

而且我找不到有关此方法的任何文档(org.jetbrains.kotlin.asJava.classesisPrivateOrParameterInPrivateMethod)。如果我用错了,我想知道。

感谢任何评论或建议

class PrivateVariableMPrefixDetector : Detector(), Detector.UastScanner {
    override fun getApplicableUastTypes() = listOf<Class<out UElement>>(UVariable::class.java)

    override fun createUastHandler(context: JavaContext) =
        NamingPatternHandler(context)

    class NamingPatternHandler(private val context: JavaContext) : UElementHandler() {
        override fun visitVariable(node: UVariable) {
            node.takeIf { it.isPrivateOrParameterInPrivateMethod() }
                ?.takeUnless { node.name?.first()?.equals('m') ?: false }
                ?.run {
                    process(node, node)
                }
        }

        private fun process(scope: UElement, declaration: PsiNamedElement) {
            context.report(
                ISSUE_PRIVATE_VAR_PREFIX_WITH_M,
                scope,
                context.getNameLocation(scope),
                "${declaration.name} is not named with prefix m"
            )
        }
    }
}

测试用例

@Test
    fun should_not_warn_when_public_variable_is_not_stated_with_m_prefix() {
        TestLintTask.lint()
            .files(
                TestFiles.kt(
                    """
                        class Foo {
                             val binding 
                        }
              """
                ).indented()
            )
            .issues(ISSUE_PRIVATE_VAR_PREFIX_WITH_M)
            .run()
            .expectClean()
    }

标签: androidkotlinintellij-ideaandroid-lint

解决方案


更新于 13/12/2020

JavaEvaluatorJavaContext中有一个类,我找到了一些有用的方法来检查适合我情况的变量的显式修饰符

class MyHandler(private val context: JavaContext) : UElementHandler() {
     override fun visitField(node: UField) {
            val isConstant = node.isFinal && node.isStatic
            val isEnumConstant = node is UEnumConstant
            if (!isConstant && !isEnumConstant) {
                node.takeIf {
                    context.evaluator.hasModifiers(node, KtTokens.PRIVATE_KEYWORD)
                }?.run {
                        process(node, node)
                    }
            }
        }
}

过时的

经过努力,我发现以下解决方案有效。虽然我还是不太明白 的意思node.sourcePsi,但我会先让它工作。感谢任何意见或建议

        node.takeIf { node.sourcePsi?.text?.startsWith("private") ?: false }
            ?.takeUnless { node.name.first() == 'm' && node.name.getOrNull(1)?.isUpperCase() ?: false }
            ?.run {
                process(node, node)
            }

推荐阅读