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

如何在Java SonarQube自定义规则中获取方法调用返回的对应字段

实现思路

  • 从MethodInvocationTree中获取调用的方法符号MethodSymbol,可以直接调用methodInvocation.symbol()拿到
  • 获取该方法所属的类的类型符号,遍历类下的所有字段,匹配和当前getter方法对应的字段
  • 检查匹配到的字段上是否存在指定的MyAnnotation注解,不存在则触发违规提示

完整实现代码

import org.sonar.plugins.java.api.IssuableSubscriptionVisitor;
import org.sonar.plugins.java.api.semantic.Symbol;
import org.sonar.plugins.java.api.semantic.SymbolMetadata;
import org.sonar.plugins.java.api.tree.*;
import java.util.Collections;
import java.util.List;

public class MyObjectCheck extends IssuableSubscriptionVisitor {

    // 替换为你实际的注解全限定名
    private static final String MY_ANNOTATION_FQN = "com.your.package.MyAnnotation";
    // 替换为MyObject类的全限定名,避免类名重复误判
    private static final String MY_OBJECT_FQN = "com.your.package.MyClass.MyObject";

    @Override
    public List<Tree.Kind> nodesToVisit() {
        return Collections.singletonList(Tree.Kind.NEW_CLASS);
    }

    @Override
    public void visitNode(Tree tree) {
        NewClassTree ctor = (NewClassTree) tree;
        if (!ctor.identifier().symbolType().is(MY_OBJECT_FQN)) {
            return;
        }
        if (ctor.arguments().size() != 1) {
            return;
        }
        ExpressionTree arg = ctor.arguments().get(0);
        if (!arg.is(Tree.Kind.METHOD_INVOCATION)) {
            // 非方法调用的参数直接判违规,可根据实际需求调整逻辑
            reportIssue(arg, "MyObject构造参数必须传入带@MyAnnotation注解的字段对应的getter返回值");
            return;
        }
        MethodInvocationTree methodInvocation = (MethodInvocationTree) arg;
        Symbol.MethodSymbol methodSymbol = methodInvocation.symbol();
        if (methodSymbol == null || methodSymbol.isUnknown()) {
            return;
        }
        // 获取方法所属的类符号
        Symbol.TypeSymbol ownerClass = methodSymbol.owner().enclosingClass();
        if (ownerClass == null) {
            return;
        }
        // 匹配getter对应的字段:示例中方法名和字段名完全一致,直接取方法名作为字段名
        // 如果是标准getXxx/isXxx格式的getter,这里可以做字符串转换:比如getAge -> age,isEnable -> enable
        String targetFieldName = methodSymbol.name();
        // 遍历类的所有成员找到匹配的字段
        Symbol.FieldSymbol matchedField = null;
        for (Symbol member : ownerClass.memberSymbols()) {
            if (member.isField() && member.name().equals(targetFieldName)) {
                matchedField = (Symbol.FieldSymbol) member;
                break;
            }
        }
        if (matchedField == null) {
            reportIssue(arg, "未找到方法对应的关联字段");
            return;
        }
        // 检查字段是否标注了指定注解
        if (!matchedField.metadata().isAnnotatedWith(MY_ANNOTATION_FQN)) {
            reportIssue(arg, "MyObject构造参数对应的字段未标注@MyAnnotation");
        }
    }
}

注意事项

  • 必须使用注解、类的全限定名做匹配,不要用短类名,避免不同包下同名类/注解的误判
  • 如果需要支持lombok自动生成的getter,需要确保SonarQube扫描时开启了lombok支持,否则无法拿到字段和方法的关联关系

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 18:30:06