【问题标题】:Custom Lint for Java / Android Report if we find a class call without implementing its interfaceCustom Lint for Java / Android Report if we find a class call without implementation its interface
【发布时间】:2016-12-19 06:36:21
【问题描述】:

为了好玩,我正在编写一个自定义的棉绒检测器。我要结束关于创建custom lint rule in Android 的 Big Nerd Ranches 课程(Java 应该也是一样)

我可以检测到我想要的事件。调用了类构造函数。然而,由于我们正在通过Abstract Syntax Tree 进行遍历 我未能检测到回调的实现。我不确定如何告诉 Java 检查文件并仅在找不到事件时报告。在这种情况下接口实现。因为我一次只能看到一片叶子。

我如何查找两个事件,存储每个事件发生的位置,然后执行我的逻辑并相应地报告?

package com.bignerdranch.linette.detectors;

import com.android.annotations.NonNull;
import com.android.tools.lint.detector.api.Category;
import com.android.tools.lint.detector.api.Context;
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.Location;
import com.android.tools.lint.detector.api.Scope;
import com.android.tools.lint.detector.api.Severity;
import com.android.tools.lint.detector.api.TextFormat;

import java.io.File;
import java.util.EnumSet;
import java.util.List;

import lombok.ast.AstVisitor;
import lombok.ast.Node;

/**
 * Lint check for the usage of to-do statements
 */
public class CallBackDetector extends Detector implements Detector.JavaScanner {

    private static final String FRAGMENT_MATCHER_STRING = "NoInternetDialogFragment()";
    private static final String INTERFACE_MATCHER_STRING =
            "NoInternetDialogFragment.NoInternetCallbackInterface";

    private static final Class<? extends Detector> DETECTOR_CLASS = CallBackDetector.class;
    private static final EnumSet<Scope> DETECTOR_SCOPE = Scope.JAVA_FILE_SCOPE;

    private static final Implementation IMPLEMENTATION = new Implementation(
            DETECTOR_CLASS,
            DETECTOR_SCOPE
    );

    private static final String ISSUE_ID = "NoInternetDialogFragment";
    private static final String ISSUE_DESCRIPTION =
            "NoInternetDialogFragment Callback not detected";
    private static final String ISSUE_EXPLANATION =
            "When using NoInternetDialogFragment you must implement its' callback -- "
                    + "NoInternetCallbackInterface";
    private static final Category ISSUE_CATEGORY = Category.CORRECTNESS;
    private static final int ISSUE_PRIORITY = 10;
    private static final Severity ISSUE_SEVERITY = Severity.ERROR;

    public static final Issue ISSUE = Issue.create(
            ISSUE_ID,
            ISSUE_DESCRIPTION,
            ISSUE_EXPLANATION,
            ISSUE_CATEGORY,
            ISSUE_PRIORITY,
            ISSUE_SEVERITY,
            IMPLEMENTATION
    );

    /**
     * Constructs a new {@link CallBackDetector} check
     */
    public CallBackDetector() {
    }

    @Override
    public boolean appliesTo(@NonNull Context context, @NonNull File file) {
        return true;
    }

    @Override
    public List<Class<? extends Node>> getApplicableNodeTypes() {
        return null;
    }

    @Override
    public AstVisitor createJavaVisitor(@NonNull JavaContext context) {
        String source = context.getContents();

        // Check validity of source
        if (source == null) {
            return null;
        }

        if(source.indexOf(INTERFACE_MATCHER_STRING) >=0){
            return null;
        }
        int index = source.indexOf(FRAGMENT_MATCHER_STRING);

        for (int i = index; i >= 0; i = source.indexOf(FRAGMENT_MATCHER_STRING, i + 1)) {
            Location location = Location.create(context.file, source, i,
                    i + FRAGMENT_MATCHER_STRING.length());
            context.report(ISSUE, location, ISSUE.getBriefDescription(TextFormat.TEXT));
        }
        return null;
    }

}

【问题讨论】:

  • 如果类构造函数将被包装到一些工厂方法中怎么办?

标签: java android abstract-syntax-tree lint


【解决方案1】:

如果您将找到的引用存储为字段并在所有语法遍历结束时报告它们,这是可能的:

createJavaVisitor 中像现在一样检查构造函数的使用。此时不要报告问题,而是在您的 CallBackDetector 中创建一个集合字段,该字段将包含对构造函数使用的引用。然后,您将得到所有构造函数使用的列表。

现在也在createJavaVisitor 内部检查任何实现您正在搜索的接口的类并将其添加到另一个字段集合中。

您可以覆盖 Detector 中的方法 afterCheckProject (api here) 以了解其何时完成。在此方法中,遍历您的两个集合并从两个集合中删除任何匹配对的项(构造函数和正在实现的接口)。任何一个集合中剩下的都是您的 Lint 错误,此时您可以将它们添加为问题。

【讨论】:

    猜你喜欢
    • 2021-03-21
    • 2019-10-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-10
    • 1970-01-01
    • 2022-12-01
    • 2023-02-24
    相关资源
    最近更新 更多