如何在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)来报告问题而不是在传感器内提出问题。
对于更复杂的分析方案,我们需要将一些信息收集到传感器实现中 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)来报告问题而不是在传感器内提出问题。