如何在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
相关产品推荐
相关产品推荐

