自定义 lint 规则,确保不调用特定方法

2024-04-27

我想确保在我的 Android 应用程序(Java 和 Kotlin 代码中)中不会调用特定类的特定方法。假设,我有一个名为Bar有两种方法:allowed() and disallowed()。这是代码:

package com;

public class Bar {

    public void disallowed() {
    }

    public void allowed() {
    }
}

假设客户端代码可以调用allowed()并且不应该打电话disallowed()。我找到了Google的内置源代码添加Javascript接口检测器 https://android.googlesource.com/platform/tools/base/+/studio-master-dev/lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/AddJavascriptInterfaceDetector.kt这与我的情况类似。

这是我的 lint 规则的代码:

样本代码检测器

package com.sample.mobile.lint

import com.android.tools.lint.detector.api.Category
import com.android.tools.lint.detector.api.Detector
import com.android.tools.lint.detector.api.Implementation
import com.android.tools.lint.detector.api.Issue
import com.android.tools.lint.detector.api.JavaContext
import com.android.tools.lint.detector.api.Scope
import com.android.tools.lint.detector.api.Severity
import com.android.tools.lint.detector.api.SourceCodeScanner
import com.intellij.psi.PsiMethod
import org.jetbrains.uast.UCallExpression


class SampleCodeDetector : Detector(), SourceCodeScanner {

    companion object {
        @JvmField
        val ISSUE = Issue.create(
                // ID: used in @SuppressLint warnings etc
                "Usage of Bar#disallowed()",

                // Title -- shown in the IDE's preference dialog, as category headers in the
                // Analysis results window, etc
                "Usage of Bar#disallowed() - Summary",

                // Full explanation of the issue; you can use some markdown markup such as
                // `monospace`, *italic*, and **bold**.
                "This check highlights the usage of Bar#disallowed()",
                Category.CORRECTNESS,
                8,
                Severity.ERROR,
                Implementation(
                        SampleCodeDetector::class.java,
                        Scope.JAVA_FILE_SCOPE
                )
        )

        const val FULLY_QUALIFIED_CLASS_NAME = "com.Bar"
        const val METHOD_NAME = "disallowed"
    }

    override fun getApplicableMethodNames() = listOf(METHOD_NAME)

    override fun visitMethod(context: JavaContext, node: UCallExpression, method: PsiMethod) {
        val evaluator = context.evaluator
        if (!evaluator.methodMatches(method, FULLY_QUALIFIED_CLASS_NAME, true)) {
            return
        }

        val message = "`Bar.disallowed()` should not be called"
        context.report(ISSUE, node, context.getNameLocation(node), message)

    }
}

样本问题注册表

package com.sample.mobile.lint

import com.android.tools.lint.client.api.IssueRegistry
import com.android.tools.lint.detector.api.Issue

class SampleIssueRegistry : IssueRegistry() {

    override val issues: List<Issue> get() = listOf(SampleCodeDetector.ISSUE)
}

构建.gradle

apply plugin: 'java-library'

dependencies {

    String lintVersion = "26.1.1"

    compileOnly "com.android.tools.lint:lint-api:$lintVersion"
    compileOnly "com.android.tools.lint:lint-checks:$lintVersion"
    compileOnly "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.2.60"

    testImplementation "com.android.tools.lint:lint:$lintVersion"
    testImplementation "com.android.tools.lint:lint-tests:$lintVersion"


}

sourceCompatibility = "1.8"
targetCompatibility = "1.8"

jar {
    manifest {
        // Only use the "-v2" key here if your checks have been updated to the
        // new 3.0 APIs (including UAST)
        attributes("Lint-Registry-v2": "com.sample.mobile.lint.SampleIssueRegistry")
    }
}

样本代码检测器测试

package com.sample.mobile.lint

import com.android.tools.lint.checks.infrastructure.LintDetectorTest
import com.android.tools.lint.detector.api.Detector

class SampleCodeDetectorTest : LintDetectorTest() {

    private val javaFile = "package com.sample.mobile.app;\n" +
            "\n" +
            "import android.util.Log;\n" +
            "\n" +
            "import com.Bar;\n" +
            "\n" +
            "public class Foo {\n" +
            "\n" +
            "    public void calLLog() {\n" +
            "        int a = 2;\n" +
            "        int b = 8;\n" +
            "        Log.d(\"Tag\", \"a+b=\" + (a + b));\n" +
            "        \n" +
            "        Bar bar = new Bar();\n" +
            "        bar.allowed();\n" +
            "        bar.disallowed();\n" +
            "    }\n" +
            "}\n"

    fun testJava() {
        lint().files(LintDetectorTest.java(javaFile))
                .run()
                .expect("")
    }

    override fun getDetector(): Detector? {
        return SampleCodeDetector()
    }

    override fun getIssues() = listOf(SampleCodeDetector.ISSUE)
}

不幸的是,测试失败了:

org.junit.ComparisonFailure: 
Expected :
Actual   :No warnings.

当然,预期的结果不是空字符串,但无论如何,“没有警告”。是不正确的,因为有一个调用Bar#disallowed() in class Foo


您还应该包含以下源代码com.Bar类进入你的测试:

import com.android.tools.lint.checks.infrastructure.LintDetectorTest
import com.android.tools.lint.detector.api.Detector

class SampleCodeDetectorTest : LintDetectorTest() {

    private val javaFile = """
        package com.sample.mobile.app;

        import android.util.Log;

        import com.Bar;

        public class Foo {

            public void calLLog() {
                int a = 2;
                int b = 8;
                Log.d("Tag", "a+b=" + (a + b));

                Bar bar = new Bar();
                bar.allowed();
                bar.disallowed();
            }
        }
    """.trimIndent()

    private val barJavaFile = """
        package com;

        public class Bar {

            public void disallowed() {
            }

            public void allowed() {
            }
        }
    """.trimIndent()

    fun testJava() {
        lint().files(java(javaFile), java(barJavaFile))
                .run()
                .expect("""
                    src/com/sample/mobile/app/Foo.java:16: Error: Bar.disallowed() should not be called [Usage of Bar#disallowed()]
                            bar.disallowed();
                                ~~~~~~~~~~
                    1 errors, 0 warnings
                """.trimIndent())
    }

    override fun getDetector(): Detector? {
        return SampleCodeDetector()
    }

    override fun getIssues() = listOf(SampleCodeDetector.ISSUE)
}

Lint 只是不知道什么com.Bar是并默默地忽略它。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

自定义 lint 规则,确保不调用特定方法 的相关文章

  • Calendar.getInstance(TimeZone.getTimeZone("UTC")) 不返回 UTC 时间

    我对得到的结果真的很困惑Calendar getInstance TimeZone getTimeZone UTC 方法调用 它返回 IST 时间 这是我使用的代码 Calendar cal Two Calendar getInstance
  • 在旋转时从错误的资源文件夹中提取可绘制对象

    在这里拉我的头发 因此 我正在使用一个具有多种类型的可绘制对象的应用程序 并且它们的结构如下 res Portrait resources drawable mdpi drawable hdpi drawable xhdpi Landsca
  • 将 SignedHash 插入 PDF 中以进行外部签名过程 -workingSample

    遵循电子书第 4 3 3 节 PDF 文档的数字签名 https jira nuxeo com secure attachment 49931 digitalsignatures20130304 pdf 我正在尝试创建一个工作示例 其中 客
  • Android:滚动 Horizo​​ntalScrollView 时如何禁用 ScrollView 的垂直滚动?

    我正在开发一个带有带有 ScrollView 的 Activity 的 Android 应用程序 其中包含 Horizo ntalScrollView 等内容 当我触摸 Horizo ntalScrollView 时 我想禁用外部 Scro
  • Java 中的“Lambdifying”scala 函数

    使用Java和Apache Spark 已用Scala重写 面对旧的API方法 org apache spark rdd JdbcRDD构造函数 其参数为 AbstractFunction1 abstract class AbstractF
  • 普罗米修斯指标 - 未找到

    我有 Spring Boot 应用程序 并且正在使用 vertx 我想监控服务和 jvm 为此我选择了 Prometheus 这是我的监控配置类 Configuration public class MonitoringConfig Bea
  • 在 Android 中调整可绘制对象的大小

    我正在为进度对话框设置一个可绘制对象 pbarDialog 但我的问题是我想每次调整可绘制的大小 但不知道如何调整 这是一些代码 Handler progressHandler new Handler public void handleM
  • Javafx过滤表视图

    我正在尝试使用文本字段来过滤表视图 我想要一个文本字段 txtSearch 来搜索 nhs 号码 名字 姓氏 和 分类类别 我尝试过在线实施各种解决方案 但没有运气 我对这一切仍然很陌生 所以如果问得不好 我深表歉意 任何帮助将不胜感激 我
  • Android 后台服务示例,具有交互式调用方法

    我不是 Android 方面的专家 我正在寻找一个 Android 应用程序的示例 该应用程序使用一个服务 其中有真正的功能方法 或者换句话说 一个服务可以用来做什么 我们什么时候需要它 超越简单的东西服务举例 我确信您渴望获得一些工作代码
  • Struts 2 + Sitemesh 3 集成 - FreemarkerDecoratorServlet 中的 NPE

    我将 Struts 2 版本 2 3 14 3 与 Sitemesh 3 版本 3 0 alpha 2 一起使用 并且在某些情况下遇到 NullPointerException 首先 这是我的 web xml 中的 struts2 site
  • 按钮 - 单击时更改背景颜色

    我的活动中有 8 个按钮 我正在寻找的是 按钮具有默认背景 单击按钮时 背景颜色应更改为其他颜色 这部分非常简单 但是 当我单击任何其他按钮时 第一个按钮的背景颜色应该变回默认颜色 我知道这将使用 选择器状态 来完成 但我不太确定如何实现它
  • 游戏内的java.awt.Robot?

    我正在尝试使用下面的代码来模拟击键 当我打开记事本时 它工作正常 但当我打开我想使用它的游戏时 它没有执行任何操作 所以按键似乎不起作用 我尝试模拟鼠标移动和点击 这些动作确实有效 有谁知道如何解决这个问题 我发现这个问题 如何在游戏中使用
  • 模块中的类无法加载

    我正在开发一个 2D Unity android 游戏 其中我最近添加了 Firebase Beta SDK 但添加后FirebaseAnalytics unitypackage我面临的错误是 无法加载模块中的类 当我删除文件夹时Fireb
  • 替换后增量

    我自己已经有一个问题了 但我想扩展它后增量示例 https stackoverflow com questions 51308967 post increment with example char a D int b 5 System o
  • Java中的Object类是什么?

    什么是或什么类型private Object obj Object http download oracle com javase 6 docs api java lang Object html是Java继承层次结构中每个类的最终祖先 从
  • spring中如何使用jackson代替JdkSerializationRedisSerializer

    我在我的一个 Java 应用程序中使用 Redis 并且正在序列化要存储在 Redis 中的对象列表 但是 我注意到使用 RedisTemplate 会使用 JdkSerializationRedisSerializer 相反 我想使用 J
  • 具有特定参数的 Spring AOP 切入点

    我需要创建一个我觉得很难描述的方面 所以让我指出一下想法 com x y 包 或任何子包 中的任何方法 一个方法参数是接口 javax portlet PortletRequest 的实现 该方法中可能有更多参数 它们可以是任何顺序 我需要
  • 如何在基本活动中使用 ViewBinding 的抽象?

    我正在创建一个基类 以便子级的所有绑定都将设置在基类中 我已经做到了这一点 abstract class BaseActivity2 b AppCompatActivity private var viewBinding B null pr
  • 使用 JobScheduler API 进行位置更新

    下面是我使用 FireBaseJobDispatcher 启动作业的演示代码 public class MainActivity extends AppCompatActivity Override protected void onCre
  • 带有 Maven Wrapper 的 Java 17 导致无法识别的 VM 选项“MaxPermSize=512m”

    I use OpenJDK 17 https jdk java net 17 使用 Maven Wrapper 3 8 2 从春季初始化 https start spring io Maven项目 JAR打包 Java 17 Spring

随机推荐