如何在sonarqube插件中构建树时获取节点访问者的行号

How to obtain line number at the node visitor during tree building in sonarqube plugin

对于更复杂的分析方案,我们需要将一些信息收集到传感器实现中 class 和下一行编号绑定。

在哪里可以找到树元素的行号?

java.plugin.version:3.13.1 sonar.plugin.api.version: 5.2

可能是新版本功能更强大?

我们的目标 - 检查包名称和 class 包含一些命名约定细节的名称,不得导入某些包。

从节点访问者我们无法看到所有树节点,这是显而易见的。 但是在这里我们可以通过 addIssue() 的内部机制为节点特定代码位置注册问题。

/**
* First step implementation of node visitor for complex multinode check
*/
@Rule(key = "ImportClassCheck",
  name = "Import classes should not contain web or form", 
  description = "Import classes should not contain web or form", 
  priority = Priority.CRITICAL, 
  tags = {"bug" })

public class ImportClassCheck extends IssuableSubscriptionVisitor {

@Override
public List<Kind> nodesToVisit() {
    return ImmutableList.of(Tree.Kind.IMPORT, Tree.Kind.PACKAGE, Tree.Kind.CLASS);
}

@Override
public void visitNode(Tree tree) {
    if (JavaCodeSensor.packages.get(context.getFileKey()) == null) {
        JavaCodeSensor.packages.put(context.getFileKey(), new ImportClassCheckState());
        JavaCodeSensor.packages.get(context.getFileKey()).file = context.getFile();
    }

    if (tree.is(Kind.PACKAGE))
        JavaCodeSensor.packages.get(context.getFileKey()).packageTree = (PackageDeclarationTree) tree;

    if (tree.is(Kind.CLASS))
            JavaCodeSensor.packages.get(context.getFileKey()).classTree.add((ClassTree) tree);

    if (tree.is(Kind.IMPORT))
        JavaCodeSensor.packages.get(context.getFileKey()).importTree.add((ImportTree) tree);
}
}

然后我们来看看 analyse() 的传感器接口实现 - 哎呀,这里没有关于为 class 名称注册问题的代码行的信息,例如在 class 行声明,无需再次解析文件。

/** 
* First step to register an Issue
*/
@Override
public void analyse(Project project, SensorContext sensorContext) {
    for (Entry<String, ImportClassCheckState> entry : packages.entrySet()) {
        if (entry.getValue().isRuleFails()) {
            NewIssue newIssue = sensorContext.newIssue().forRule(
                                RuleKey.of("java-custom-rules-template", "ImportClassCheck"));
            newIssue.at(newIssue.newLocation()
                    .on(filesystem
                            .inputFile(filesystem.predicates().is(entry.getValue().file)))
/* Here is a problem to identify code of line, but needed tree nodes are exists in 
ImportClassCheckState members*/
                            .at(new DefaultTextRange(new DefaultTextPointer(1, 0), 
                        new DefaultTextPointer(1, 0))));
            newIssue.save();

            logger.info("Issue registered for file " + entry.getValue().file.getName());
        }
    }
}

多种方式来回答你的问题。

让我先改写一下:如何从树的一个节点访问行信息。

回答这个问题的最佳方法:升级到最新版本 (4.2) 并使用树的每个节点上可用的 firstSyntaxToken().line() 方法。

但更好的是您根本不需要它,您应该使用 issuableSubscriptionVisitor 中可用的方法(addIssue 或 reportIssue)来报告问题而不是在传感器内提出问题。