0

I am writing a tool for collecting class comments, and I would like to gather all comments that are logically attached to a class by developers:

public abstract class A {

  private Integer d;



   // comment line
   /**
   * javadoc comment
   */
   class B {
     int c;
   }
 }

or (reversed order of comments)

public abstract class A {
   /**
   * javadoc comment
   */
   // comment line
   class B {
     int c;
   }
 }

my current implementation traverses recursively starting from CompilationUnit to each child (Node) and checks if it is a class(or interface) declaration. Then the comment is extracted from the Node through node.getComment() . The problem is, that the other comment located on top of the first has no parent and therefore is not being counted.

Is there a way to somehow collect all of them? (lets consider they're located next to each other, without new line skips)

  • Related issues, some of which give suggestions (but not code) for solving your problem: https://github.com/javaparser/javaparser/issues/263 https://github.com/javaparser/javaparser/issues/498 https://github.com/javaparser/javaparser/issues/1190 https://github.com/javaparser/javaparser/issues/2346 https://github.com/javaparser/javaparser/issues/2600 – mernst Apr 09 '20 at 05:31

1 Answers1

1

Here is a solution. Credit goes to Waylon Huang who wrote this code.

  /**
   * This is stolen from JavaParser's PrettyPrintVisitor.printOrphanCommentsBeforeThisChildNode,
   * with light modifications.
   *
   * @param node the node whose orphan comments to collect
   * @param result the list to add orphan comments to. Is side-effected by this method. The
   *     implementation uses this to minimize the diffs against upstream.
   */
  @SuppressWarnings({
    "JdkObsolete", // for LinkedList
    "ReferenceEquality"
  })
  private static void getOrphanCommentsBeforeThisChildNode(final Node node, List<Comment> result) {
    if (node instanceof Comment) {
      return;
    }

    Node parent = node.getParentNode().orElse(null);
    if (parent == null) {
      return;
    }
    List<Node> everything = new LinkedList<>(parent.getChildNodes());
    sortByBeginPosition(everything);
    int positionOfTheChild = -1;
    for (int i = 0; i < everything.size(); i++) {
      if (everything.get(i) == node) positionOfTheChild = i;
    }
    if (positionOfTheChild == -1) {
      throw new AssertionError("I am not a child of my parent.");
    }
    int positionOfPreviousChild = -1;
    for (int i = positionOfTheChild - 1; i >= 0 && positionOfPreviousChild == -1; i--) {
      if (!(everything.get(i) instanceof Comment)) positionOfPreviousChild = i;
    }
    for (int i = positionOfPreviousChild + 1; i < positionOfTheChild; i++) {
      Node nodeToPrint = everything.get(i);
      if (!(nodeToPrint instanceof Comment))
        throw new RuntimeException(
            "Expected comment, instead "
                + nodeToPrint.getClass()
                + ". Position of previous child: "
                + positionOfPreviousChild
                + ", position of child "
                + positionOfTheChild);
      result.add((Comment) nodeToPrint);
    }
  }
}
mernst
  • 7,437
  • 30
  • 45