org.checkerframework.framework.ajava.AnnotationEqualityVisitor Maven / Gradle / Ivy
Show all versions of checker Show documentation
package org.checkerframework.framework.ajava;
import com.github.javaparser.ast.Node;
import com.github.javaparser.ast.comments.Comment;
import com.github.javaparser.ast.expr.AnnotationExpr;
import com.github.javaparser.ast.nodeTypes.NodeWithAnnotations;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.List;
/**
* Given two ASTs representing the same Java file that may differ in annotations, tests if they have
* the same annotations.
*
* To use this class, have the first AST node accept the visitor and pass the second AST node as
* the second argument. Then, check {@link #getAnnotationsMatch}.
*/
public class AnnotationEqualityVisitor extends DoubleJavaParserVisitor {
/** Whether or not a node with mismatched annotations has been seen. */
private boolean annotationsMatch;
/** If a node with mismatched annotations has been seen, stores the node from the first AST. */
private @MonotonicNonNull NodeWithAnnotations> mismatchedNode1;
/** If a node with mismatched annotations has been seen, stores the node from the second AST. */
private @MonotonicNonNull NodeWithAnnotations> mismatchedNode2;
/** Constructs an {@code AnnotationEqualityVisitor}. */
public AnnotationEqualityVisitor() {
annotationsMatch = true;
mismatchedNode1 = null;
mismatchedNode2 = null;
}
/**
* Returns whether a visited pair of nodes differed in annotations.
*
* @return true if some visited pair of nodes differed in annotations
*/
public boolean getAnnotationsMatch() {
return annotationsMatch;
}
/**
* If a visited pair of nodes has had mismatched annotations, returns the node from the first
* AST where annotations differed, or null otherwise.
*
* @return the node from the first AST with differing annotations or null
*/
public @Nullable NodeWithAnnotations> getMismatchedNode1() {
return mismatchedNode1;
}
/**
* If a visited pair of nodes has had mismatched annotations, returns the node from the second
* AST where annotations differed, or null otherwise.
*
* @return the node from the second AST with differing annotations or null
*/
public @Nullable NodeWithAnnotations> getMismatchedNode2() {
return mismatchedNode2;
}
@Override
public void defaultAction(T node1, T node2) {
if (!(node1 instanceof NodeWithAnnotations>)
|| !(node2 instanceof NodeWithAnnotations>)) {
return;
}
// Comparing annotations with "equals" considers comments in the AST attached to the
// annotations. These should be ignored because two valid ASTs for the same file may differ
// in where comments appear, or whether they appear at all. So, to check if two nodes have
// the same annotations we create copies with all comments removed and compare their lists
// of annotations directly.
Node node1Copy = node1.clone();
Node node2Copy = node2.clone();
for (Comment comment : node1Copy.getAllContainedComments()) {
comment.remove();
}
for (Comment comment : node2Copy.getAllContainedComments()) {
comment.remove();
}
List node1annos = ((NodeWithAnnotations>) node1Copy).getAnnotations();
List node2annos = ((NodeWithAnnotations>) node2Copy).getAnnotations();
if (!node1annos.equals(node2annos)) {
annotationsMatch = false;
mismatchedNode1 = (NodeWithAnnotations>) node1;
mismatchedNode2 = (NodeWithAnnotations>) node2;
}
}
}