1

For more complex analysis puproses we need to collect some info into Sensor implementation class and next line number binding.

Where can I find line number of tree element?

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

May be newer versions are more functional?

Our goal - to check that package name and class name, containing some naming conventions details, must not import some packages.

From the node visitor we unable to see all tree nodes, it's obvious. But here we can register an issue for node specific place of code by internal mechanism of 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);
}
}

Then we come to Sensor interface implementation of analyse() - Oops, here is no info about line of code to register an issue for class name, for example at the line of class declaration, without parsing of file again.

/** 
* 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());
        }
    }
}

1 Answers1

4

Multiple way to answer your question.

Let me rephrase it first : how to access line information from a node of the tree.

Best way to answer just this question : upgrade to the latest version (4.2) and use the firstSyntaxToken().line() methods available on each node of the tree.

But what is better is that you don't need this at all, you should use the methods available in the issuableSubscriptionVisitor (either addIssue or reportIssue) to report issue and not raise issue within the sensor.

benzonico
  • 10,635
  • 5
  • 42
  • 50