【问题标题】:Custom lint rule for the `when condition` check`when condition` 检查的自定义 lint 规则
【发布时间】:2019-09-25 22:02:16
【问题描述】:

我正在使用 Gson 的序列化适配器 RuntimeTypeAdapterFactory 基于鉴别器对数据进行序列化。但是,当存在未知的鉴别器(来自 API)并且未在客户端上定义时,TypeAdapter 将为空。

在这种情况下,如果我在条件检查时有一个 kotlin:

when(fooType){
 is fooA -> //blaba
 is fooB -> //blaba
 //else or null is not handled
}

而fooType 是null,它会因为null 条件未处理而崩溃。 如果他们实现else 或 null检查并注入 Android Studio 检查?

【问题讨论】:

    标签: android android-studio kotlin jetbrains-ide lint


    【解决方案1】:

    我真的没有编写自定义 lint 检查的经验,但我认为这样的事情(虽然它不是最佳的,你不应该按原样使用它,因为它只显示了这个想法) 可能会起作用。

    class WhenNullElseMissingDetector : Detector(), Detector.UastScanner {
    
        override fun getApplicableUastTypes(): MutableList<Class<out UElement>> =
            mutableListOf(USwitchExpression::class.java)
    
        override fun createUastHandler(context: JavaContext): UElementHandler = WhenNullElseMissingHandler(context)
    }
    
    class WhenNullElseMissingHandler(private val context: JavaContext) : UElementHandler() {
    
        override fun visitSwitchExpression(node: USwitchExpression) {
            if (node.psi?.javaClass != KtWhenExpression::class.java) {
                // returning early here, so it doesn't go false positive on java switches
                return
            }
    
            var hasNullClause = false
            var hasElseClause = false
    
            node.body.expressions.forEach { clause ->
                 // checking the child's text here just for a example, you should
                 // probably check if child's class is KtWhenConditionIsPattern,
                 // KtWhenConditionWithExpression or LeafPsiElement
                val clauseText = clause.psi?.firstChild?.text
    
                if ("null" == clauseText) {
                    hasNullClause = true
                } else if ("else" == clauseText) {
                    hasElseClause = true
                }
            }
    
            if (!hasElseClause) {
                context.report(
                    WHEN_NULL_OR_ELSE_MISSING, node, context.getLocation(node),
                    "When expression must include an else case"
                )
            }
    
            if (!hasNullClause) {
                context.report(
                    WHEN_NULL_OR_ELSE_MISSING, node, context.getLocation(node),
                    "When expression must include a null case"
                )
            }
        }
    }
    

    当然,您必须将新检测器添加到 IssueRegistry。 假设您在单独的 java/kotlin 模块中进行 lint 检查,它可能看起来像这样

    package com.example.lintchecks
    
    // omit imports
    
    val WHEN_NULL_OR_ELSE_MISSING = Issue.create(
        "MY_ISSUE_ID",
        "A brief to show in a one line popup",
        "More detailed explanation",
        Category.CORRECTNESS,
        5,
        Severity.WARNING,
        Implementation(
            WhenNullElseMissingDetector::class.java,
            Scope.JAVA_FILE_SCOPE
        )
    )
    
    class MyIssueRegistry : IssueRegistry() {
        override val issues: List<Issue>
            get() = listOf(WHEN_NULL_OR_ELSE_MISSING)
    
    }
    

    库模块的 build.gradle 文件应该有 com.android.tools.lint:lint-api:26.4.0(或任何相关版本)compileOnly 依赖和这样的块

    jar {
        manifest {
            attributes("Lint-Registry-v2": "com.example.lintchecks.MyIssueRegistry")
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2014-10-30
      • 1970-01-01
      • 1970-01-01
      • 2021-03-17
      • 2013-05-20
      • 2016-01-18
      • 2018-09-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多