You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在IntelliJ IDEA中编写自定义检查规则检测重复@Link注解值

IDEA自定义检查工具实现@Link注解value全局重复检测

核心实现步骤

1. 项目级全局缓存实现

因为需要跨Java文件检测重复,首先要实现项目级的全局缓存,存储所有@Link注解的value值与对应方法PSI元素的映射,并且要监听文件变动事件,动态更新缓存内容,避免缓存失效。

// 项目级缓存示例
public class LinkValueCache implements ProjectComponent {
    private final Project project;
    private final Map<String, List<PsiMethod>> valueToMethods = new ConcurrentHashMap<>();

    public static LinkValueCache getInstance(Project project) {
        return project.getComponent(LinkValueCache.class);
    }

    public LinkValueCache(Project project) {
        this.project = project;
    }

    // 新增value与方法的映射
    public void addValue(String value, PsiMethod method) {
        valueToMethods.computeIfAbsent(value, k -> new ArrayList<>()).add(method);
    }

    // 查询value对应的所有方法
    public List<PsiMethod> getMethodsByValue(String value) {
        return valueToMethods.getOrDefault(value, Collections.emptyList());
    }

    // 文件变更时清理对应文件的缓存
    public void removeFileCache(VirtualFile file) {
        // 遍历缓存删除该文件下所有方法的映射
        valueToMethods.values().forEach(list -> list.removeIf(method -> 
            method.getContainingFile().getVirtualFile().equals(file)
        ));
        valueToMethods.entrySet().removeIf(entry -> entry.getValue().isEmpty());
    }
}

2. 自定义检查类实现

继承IDEA提供的AbstractBaseJavaLocalInspectionTool类,实现对方法上@Link注解的扫描逻辑:

public class LinkValueDuplicateInspection extends AbstractBaseJavaLocalInspectionTool {
    @NotNull
    @Override
    public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
        return new JavaElementVisitor() {
            @Override
            public void visitMethod(@NotNull PsiMethod method) {
                super.visitMethod(method);
                // 读取方法上的@Link注解,替换为你实际的@Link注解全类名
                PsiAnnotation linkAnno = method.getAnnotation("com.xxx.Link");
                if (linkAnno == null) return;
                // 读取value属性值
                PsiAnnotationMemberValue valueAttr = linkAnno.findAttributeValue("value");
                if (!(valueAttr instanceof PsiLiteralExpression valueLiteral)) return;
                Object valueObj = valueLiteral.getValue();
                if (valueObj == null) return;
                String value = valueObj.toString();
                // 从全局缓存判断是否重复
                List<PsiMethod> sameValueMethods = LinkValueCache.getInstance(method.getProject()).getMethodsByValue(value);
                if (sameValueMethods.size() >= 2) {
                    holder.registerProblem(
                        valueAttr,
                        "@Link注解value值全局不唯一,存在重复",
                        ProblemHighlightType.ERROR
                    );
                }
            }
        };
    }
}

3. 注册检查与监听

在插件的plugin.xml配置文件中注册自定义检查和文件变动监听器:

<!-- 注册自定义检查 -->
<localInspection
    language="JAVA"
    shortName="LinkValueDuplicate"
    displayName="@Link注解value重复检测"
    groupName="注解校验"
    groupPath="Java"
    enabledByDefault="true"
    level="ERROR"
    implementationClass="com.xxx.LinkValueDuplicateInspection"/>

<!-- 注册文件变动监听器,动态更新缓存 -->
<applicationListener
    listener="com.intellij.openapi.vfs.VirtualFileListener"
    implementationClass="com.xxx.LinkValueCacheUpdateListener"/>

最终效果

对于示例代码,两个value = "123456"的@Link注解都会被高亮标注错误:

// 此处高亮提示重复
@Link(type = "manual", value = "123456")
void someTest1(){
}

@Link(type = "manual", value = "654321")
void someTest2(){
}

// 此处同样高亮提示重复
@Link(type = "manual", value = "123456")
void someTest3(){
}

优化建议

  • 如果项目体量较大,可改用IDEA自定义索引功能实现全局检索,降低全量扫描的性能损耗
  • 可新增快速修复功能,自动生成不重复的value值填充到注解中

内容的提问来源于stack exchange,提问作者pro100filimon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 01:54:02