delegate the range contains check and added comments to make it explicit that it is a "strict contains" check. (re: #398, this would mean a correction to `<=` to exclude the end overlapping)
diff --git a/javaparser-core/src/main/java/com/github/javaparser/utils/PositionUtils.java b/javaparser-core/src/main/java/com/github/javaparser/utils/PositionUtils.java
index 8daaa05..3e0e032 100644
--- a/javaparser-core/src/main/java/com/github/javaparser/utils/PositionUtils.java
+++ b/javaparser-core/src/main/java/com/github/javaparser/utils/PositionUtils.java
@@ -22,8 +22,6 @@
package com.github.javaparser.utils;
import com.github.javaparser.Position;
-import com.github.javaparser.Range;
-import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.Node;
import com.github.javaparser.ast.NodeList;
import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
@@ -36,7 +34,6 @@
import java.util.List;
import java.util.Objects;
-import java.util.Optional;
import static java.lang.Integer.signum;
@@ -110,15 +107,15 @@
}
private static int beginLineWithoutConsideringAnnotation(Node node) {
- return beginNodeWithoutConsideringAnnotations(node).getRange().get().begin.line;
+ return nodeWithoutConsideringAnnotations(node).getRange().get().begin.line;
}
private static int beginColumnWithoutConsideringAnnotation(Node node) {
- return beginNodeWithoutConsideringAnnotations(node).getRange().get().begin.column;
+ return nodeWithoutConsideringAnnotations(node).getRange().get().begin.column;
}
- private static Node beginNodeWithoutConsideringAnnotations(Node node) {
+ private static Node nodeWithoutConsideringAnnotations(Node node) {
if (node instanceof MethodDeclaration || node instanceof FieldDeclaration) {
NodeWithType<?, Type> casted = (NodeWithType<?, Type>) node;
return casted.getType();
@@ -131,65 +128,37 @@
}
/**
- * Compare nodes. Optionally include annotations in the range checks.
+ * Compare the position of two nodes. Optionally include annotations within the range checks.
* This method takes into account whether the nodes are within the same compilation unit.
- *
- * @param container
- * @param other
- * @param ignoringAnnotations
- * @return
+ * <p>
+ * Note that this performs a "strict contains", where the container must extend beyond the other node in both
+ * directions (otherwise it would count as an overlap, rather than "contain").
*/
public static boolean nodeContains(Node container, Node other, boolean ignoringAnnotations) {
- if(!container.getRange().isPresent()) {
+ if (!container.getRange().isPresent()) {
throw new IllegalArgumentException("Cannot compare the positions of nodes if container node does not have a range.");
}
- if(!other.getRange().isPresent()) {
+ if (!other.getRange().isPresent()) {
throw new IllegalArgumentException("Cannot compare the positions of nodes if contained node does not have a range.");
}
- if(!Objects.equals(container.findCompilationUnit(), other.findCompilationUnit())) {
+ if (!Objects.equals(container.findCompilationUnit(), other.findCompilationUnit())) {
// Allow the check to complete if they are both within a known CU (i.e. the CUs are the same),
// ... or both not within a CU (i.e. both are Optional.empty())
return false;
}
- final boolean hasAnnotations = !(container instanceof NodeWithAnnotations) || PositionUtils.getLastAnnotation(container) != null;
- if ((!ignoringAnnotations || !hasAnnotations)) {
+ final boolean nodeCanHaveAnnotations = container instanceof NodeWithAnnotations;
+ final boolean hasAnnotations = PositionUtils.getLastAnnotation(container) != null;
+ if ((!ignoringAnnotations || !nodeCanHaveAnnotations || !hasAnnotations)) {
// No special consideration required - perform simple range check.
return container.containsWithinRange(other);
}
- // Is this an unwarranted (potentially backfiring?) micro-optimisation?
- if (!container.containsWithinRange(other)) {
- // If not in the looser range check, certainly will not be in narrower range check.
- return false;
- }
-
-
- final Range containerRange = container.getRange().get();
- final Range otherRange = other.getRange().get();
-
- // if the node is contained, but it comes immediately after the annotations,
- // let's not consider it contained
- int containerStartLine = beginLineWithoutConsideringAnnotation(container);
- int containerStartColumn = beginColumnWithoutConsideringAnnotation(container);
-
- if (otherRange.begin.line < containerStartLine) {
- // Other node starts before the container starts
- return false;
- } else if (otherRange.begin.line == containerStartLine && otherRange.begin.column < containerStartColumn) {
- // Same start line, but earlier column start -- note this permits equal start columns
- return false;
- } else if (otherRange.end.line > containerRange.end.line) {
- // Other node ends after the container ends
- return false;
- } else if (otherRange.end.line == containerRange.end.line && otherRange.end.column > containerRange.end.column) {
- // Same end line, but later column end -- note this permits equal end columns
- return false;
- } else {
- // All checks pass -- must be contained.
- return true;
- }
+ // If the node is contained, but it comes immediately after the annotations,
+ // let's not consider it contained (i.e. it must be "strictly contained").
+ return nodeWithoutConsideringAnnotations(container).getRange().get()
+ .strictlyContains(other.getRange().get());
}
}