首页 > 其他分享 >Android代码检查规则Lint的自定义与应用

Android代码检查规则Lint的自定义与应用

时间:2023-06-19 10:32:33浏览次数:49  
标签:Lint 自定义 检查 lint SdkConstants FILE Android


前言:

在日常的代码开发中,此处相信每个开发人员对代码质量都是高要求,有自己的一套代码规范,但是我们不是单独作战,往往大家都是团队作战,人是最大的变量,各人各异,如何保证团队的代码质量和代码规范呢?靠开发者自觉吗?也许有的团队有严格的CR机制,在MR阶段会进行CR,CR不通过的MR是不允许合入的,但是这样会使Reviewer花费较多的时间去校验,那么这时候我们就需要在编码过程中提供一种代码检测机制。

例如:期望表现的效果就是在编码时可以展示异常检测的方法,高亮或者标红,当鼠标悬停在高亮的代码上时,会提供问题的描述和解决方法。需要这种效果,就需要自定义lint了。

Android代码检查规则Lint的自定义与应用_Kotlin

什么是Lint

在Android Studio中提供的代码扫描工具Lint,可在无需实际执行该应用,也不必编写测试用例的情况下帮助开发者发现代码质量问题和提出一些改进建议。

Lint工具可检查您的 Android 项目源文件是否包含潜在错误,以及在正确性、安全性、性能、易用性、便利性和国际化方面是否需要优化改进。在使用 Android Studio 时,配置的 Lint 和 IDE 检查会在您每次构建应用时运行。不过,您可以手动运行检查或从命令行运行 Lint。

android studio内置了较多的lint规则,但内置的lint规则无法满足直观的适合我们时,就需要我们自定义lint了。

Android代码检查规则Lint的自定义与应用_android studio_02

自定义Lint流程:

1. 新创建module,Module类型选择Java or Kotlin Library, 暂时命名lint_tools

2. 在build.gradle中引入lint的依赖

dependencies {
        compileOnly 'com.android.tools.lint:lint-api:27.2.2'
        compileOnly 'com.android.tools.lint:lint-checks:27.2.2'
    }

在moudle中依赖了lint-api和lint-checks,其中lint-api就是lint相关的api,lint-checks就是android studio里自定义的一些lint规则,我们自定义lint可以参考lint-checks里面的写法。

3. 本地创建个资源id命名检查规则,用来规范项目中的id统一命名

创建ViewIdDetector,直接继承LayoutDetector(也可以继承ResourceXmlDetector 或者 继承Detector实现的接口是XmlScanner,方式多样)

import com.android.SdkConstants
import com.android.tools.lint.detector.api.*
import com.android.tools.lint.detector.api.Category.Companion.CORRECTNESS
import com.android.tools.lint.detector.api.Scope.Companion.RESOURCE_FILE_SCOPE
import org.w3c.dom.Element

class ViewIdDetector : LayoutDetector() {
    
    override fun getApplicableElements(): Collection<String>? {
        return listOf(
            SdkConstants.TEXT_VIEW,
            SdkConstants.IMAGE_VIEW,
            SdkConstants.BUTTON
        )
    }

    override fun visitElement(context: XmlContext, element: Element) {
        if (!element.hasAttributeNS(SdkConstants.ANDROID_URI, SdkConstants.ATTR_ID)) {
            return
        }
        val attr = element.getAttributeNodeNS(SdkConstants.ANDROID_URI, SdkConstants.ATTR_ID)
        val value = attr.value
        if (value.startsWith(SdkConstants.NEW_ID_PREFIX)) {
            val idValue = value.substring(SdkConstants.NEW_ID_PREFIX.length)
            var matchRule = true
            var expMsg = ""
            when (element.tagName) {
                SdkConstants.TEXT_VIEW -> {
                    expMsg = "tv"
                    matchRule = idValue.startsWith(expMsg)
                }
                SdkConstants.IMAGE_VIEW -> {
                    expMsg = "iv"
                    matchRule = idValue.startsWith(expMsg)
                }
                SdkConstants.BUTTON -> {
                    expMsg = "btn"
                    matchRule = idValue.startsWith(expMsg)
                }
            }
            if (!matchRule) {
                context.report(
                    ISSUE, 
                    attr, 
                    context.getLocation(attr), 
                    "ViewIdName建议使用view的缩写_xxx; ${element.tagName} 建议使用 `${expMsg}_xxx`"
                )
            }
        }
    }

    companion object {
        val ISSUE: Issue = Issue.create(
            "ViewIdCheck",
            "ViewId命名不规范",
            "ViewIdName建议使用 view的缩写加上_xxx,例如tv_xxx, iv_xxx",
            CORRECTNESS,
            5, Severity.ERROR,
            Implementation(
                ViewIdDetector::class.java,
                RESOURCE_FILE_SCOPE
            )
        )
    }
}

自定义Detector可以实现一个或多个Scanner接口,选择实现哪种接口取决于你想要的扫描范围。
Lint API 中内置了很多 Scanner:

Scanner 类型

Desc

UastScanner

扫描 Java、Kotlin 源文件

XmlScanner

扫描 XML 文件

ResourceFolderScanner

扫描资源文件夹

ClassScanner

扫描 Class 文件

BinaryResourceScanner

扫描二进制资源文件

GradleScanner

扫描Gradle脚本

4. 实现IssueRegistry并添加对应的自定义Issue:

class IMockIssueRegistry: IssueRegistry() {
    override val issues: List<Issue>
        get() = listOf(
            ViewIdDetector.ISSUE
        )

}

5. 在module(lint_tools)中对应的build.gradle中配置如下信息:

jar {
    manifest {
        attributes("Lint-registry-v2": "com.imock.lint.IMockIssueRegistry")
    }
}

6. 在需要进行lint检查的module中或者app目录现的build.gradle中引用对应的lint_tools即可使用。

dependencies {
    lintChecks project(path: ':lint-tools')
}

至此你可以试着自己自定义Lint了,相关语法api都可参考lint-checks中提供的Detector实现,来实现自己的Lint检查规则。

拓展一下:

1. 针对Issue.create参数了解一下:

companion object {
    /**
     * Creates a new issue. The description strings can use some simple markup;
     * see the [TextFormat.RAW] documentation
     * for details.
     *
     * @param id the fixed id of the issue
     * @param briefDescription short summary (typically 5-6 words or less), typically
     * describing the **problem** rather than the **fix**
     * (e.g. "Missing minSdkVersion")
     * @param explanation a full explanation of the issue, with suggestions for
     * how to fix it
     * @param category the associated category, if any
     * @param priority the priority, a number from 1 to 10 with 10 being most
     * important/severe
     * @param severity the default severity of the issue
     * @param implementation the default implementation for this issue
     * @return a new [Issue]
     */
    @JvmStatic
    fun create(
        id: String,
        briefDescription: String,
        explanation: String,
        category: Category,
        priority: Int,
        severity: Severity,
        implementation: Implementation
    ): Issue {
        val platforms = computePlatforms(null, implementation)
        return Issue(
            id, briefDescription, explanation, category, priority,
            severity, platforms, null, implementation
        )
    }
}
  • 参数id 唯一的id,简要表面当前提示的问题。
  • 参数briefDescription 简单描述当前问题
  • 参数explanation 详细解释当前问题和修复建议
  • 参数category 问题类别
  • 参数priority 优先级,从1到10,10最重要
  • 参数Severity 严重程度:FATAL(奔溃), ERROR(错误), WARNING(警告),INFORMATIONAL(信息性),IGNORE(可忽略)
  • 参数Implementation Issue和哪个Detector绑定,以及声明检查的范围。Scope有如下选择范围:RESOURCE_FILE(资源文件),BINARY_RESOURCE_FILE(二进制资源文件),RESOURCE_FOLDER(资源文件夹),ALL_RESOURCE_FILES(所有资源文件),JAVA_FILE(Java文件), ALL_JAVA_FILES(所有Java文件),CLASS_FILE(class文件), ALL_CLASS_FILES(所有class文件),MANIFEST(配置清单文件), PROGUARD_FILE(混淆文件),JAVA_LIBRARIES(Java库), GRADLE_FILE(Gradle文件),PROPERTY_FILE(属性文件),TEST_SOURCES(测试资源),OTHER(其他);

2. Lint API 中 UastScanner 相关回调方法介绍

  1. getApplicableUastTypes 与 createUastHandler
  • getApplicableUastTypes 此方法返回需要检查的AST节点的类型,类型匹配的UElement将会被createUastHandler(createJavaVisitor)创建的UElementHandler(Visitor)检查。
  • createUastHandler 创建一个UastHandler来检查需要检查的UElement,对应于getApplicableUastTypes
  1. getApplicableMethodNames 与 visitMethod
  • getApplicableMethodNames 返回你所需要检查的方法名称列表,或者返回null,相匹配的方法将通过visitMethod方法被检查
  • visitMethod 检查与getApplicableMethodNames相匹配的方法
  1. getApplicableConstructorTypes 与 visitConstructor
  • getApplicableConstructorTypes 返回需要检查的构造函数类型列表,类型匹配的方法将通过visitConstructor被检查
  • visitConstructor 检查与getApplicableConstructorTypes相匹配的构造方法
  1. getApplicableReferenceNames 与 visitReference
  • getApplicableReferenceNames 返回需要检查的引用路径名,匹配的引用将通过visitReference被检查
  • visitReference 检查与getApplicableReferenceNames匹配的引用
  1. appliesToResourceRefs 与 visitResourceReference
  • appliesToResourceRefs 返回需要检查的资源引用,匹配的引用将通过visitResourceReference被检查
  • visitResourceReference 检查与appliesToResourceRefs匹配的资源引用
  1. applicableSuperClasses 与 visitClass
  • applicableSuperClasses 返回需要检查的父类名列表,此处需要类的全路径名
  • visitClass 检查applicableSuperClasses返回的类


标签:Lint,自定义,检查,lint,SdkConstants,FILE,Android
From: https://blog.51cto.com/u_16163480/6511345

相关文章

  • 【车载开发】Android车载操作系统来了,前景非常乐观
    时间回到2014年6月26日,谷歌在GoogleI/O大会的开幕式主题演讲中正式发布了手机车机映射方案AndroidAuto,旨在通过中控屏幕来使用手机内置的服务,让软件的体验更适合车载场景。2016年,谷歌又在I/O大会上展示了使用Android系统接管玛莎拉蒂Ghibli的中控系统,包括空调和......
  • Android - 无法使用任何临时 SqlClient 版本(v2.1.4、v4.1.0、v5Preview)连接到 SQL Ser
    Aconnectionwassuccessfullyestablishedwiththeserver,butthenanerroroccurredduringthepre-loginhandshake.设法用证书和IP地址解决它。使用powershell为您的IP地址创建证书:New-SelfSignedCertificate-certstorelocationcert:\localmachine\my-dns......
  • 前端Vue图片上传组件支持单个文件多个文件上传 自定义上传数量 预览删除图片 图片压缩
    前端Vue图片上传组件支持单个文件多个文件上传自定义上传数量预览删除图片图片压缩,下载完整代码请访问uni-app插件市场址:https://ext.dcloud.net.cn/plugin?id=13099效果图如下:1.0.0(2023-06-18)组件初始化使用方法<!--count:最大上传数量 imageList:图片上传选......
  • Android 12 自定义底部导航栏
    1.修改配置文件 frameworks\base\packages\SystemUI\res\values\config.xml<!--Navbarbuttondefaultordering/layout--><stringname="config_navBarLayout"translatable="false">left[.5W];leftrotate,volume_sub,back,home,r......
  • 自定义异常和统一校验参数
    自定义异常@GetterpublicclassBusinessExceptionextendsRuntimeException{/***http状态码*/privateintcode;privateObjectobject;publicBusinessException(Stringmessage,intcode,Objectobject){super(message);......
  • 浅谈生活中常见的三大应用程序架构(PE、ELF、Mach-O)、五大操作系统(windows、linux、mac
    ·今天不聊复杂的技术,就是想做一下科普。我们生活中常见的操作系统,大致有5种分别是 电脑: Windows linux    macos手机 androidiosWindows手机操作系统没有发展起来,不同的操作系统间软件不能......
  • 给Nexus6p刷入lineage14.1(android 7.1)和 nethunter 2019.3
    本文依据kali教程编写https://build.nethunter.com/contributors/re4son/angler/INSTALLATION.txt写在前面的话你可能很奇怪,为什么有kali2020.3不用要刷入2019.3版本的。其实目的是使用安卓7,因为高版本安卓对某些软件的兼容性太差,刷入2019载手动升级到2020.3.Andrax在安卓7、9......
  • Hexo + Butterfly 自定义页脚
    原文链接:Hexo+Butterfly自定义页脚推荐阅读基于Hexo从零开始搭建个人博客(一):环境准备基于Hexo从零开始搭建个人博客(二):项目初识基于Hexo从零开始搭建个人博客(三):主题安装基于Hexo从零开始搭建个人博客(四):基础配置基于Hexo从零开始搭建个人博客(五):详细......
  • backtrader 自定义分析器,解决多股回测难分析困难问题
    backtrader自定义分析器,解决多股回测分析困难问题解决了啥:解决回测后获取关键指标解决多股回测,获取订单分析解决多股回测买卖点可视化标识效果图通过自定义分析器KeyIndicatorAnalyzer,TradeListAnalyzer,获取回测结果数据,通过回测数据可以轻松可视化回测结果。可视化部......
  • 2023-06-18 as运行android项目报错:
    完整报错:Aproblemoccurredconfiguringrootproject'项目名'.>Couldnotresolvealldependenciesforconfiguration':classpath'.>Usinginsecureprotocolswithrepositories,withoutexplicitopt-in,isunsupported.Switch......