1/* 2 * Copyright (C) 2007-2010 Júlio Vilmar Gesser. 3 * Copyright (C) 2011, 2013-2016 The JavaParser Team. 4 * 5 * This file is part of JavaParser. 6 * 7 * JavaParser can be used either under the terms of 8 * a) the GNU Lesser General Public License as published by 9 * the Free Software Foundation, either version 3 of the License, or 10 * (at your option) any later version. 11 * b) the terms of the Apache License 12 * 13 * You should have received a copy of both licenses in LICENCE.LGPL and 14 * LICENCE.APACHE. Please refer to those files for details. 15 * 16 * JavaParser is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 * GNU Lesser General Public License for more details. 20 */ 21 22package com.github.javaparser.utils; 23 24import com.github.javaparser.Position; 25import com.github.javaparser.Range; 26import com.github.javaparser.ast.Node; 27import com.github.javaparser.ast.NodeList; 28import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration; 29import com.github.javaparser.ast.body.FieldDeclaration; 30import com.github.javaparser.ast.body.MethodDeclaration; 31import com.github.javaparser.ast.expr.AnnotationExpr; 32import com.github.javaparser.ast.nodeTypes.NodeWithAnnotations; 33import com.github.javaparser.ast.nodeTypes.NodeWithType; 34import com.github.javaparser.ast.type.Type; 35 36import java.util.List; 37 38import static java.lang.Integer.signum; 39 40public final class PositionUtils { 41 42 private PositionUtils() { 43 // prevent instantiation 44 } 45 46 public static <T extends Node> void sortByBeginPosition(List<T> nodes) { 47 sortByBeginPosition(nodes, false); 48 } 49 50 public static <T extends Node> void sortByBeginPosition(NodeList<T> nodes) { 51 sortByBeginPosition(nodes, false); 52 } 53 54 public static <T extends Node> void sortByBeginPosition(List<T> nodes, final boolean ignoringAnnotations) { 55 nodes.sort((o1, o2) -> PositionUtils.compare(o1, o2, ignoringAnnotations)); 56 } 57 58 public static boolean areInOrder(Node a, Node b) { 59 return areInOrder(a, b, false); 60 } 61 62 public static boolean areInOrder(Node a, Node b, boolean ignoringAnnotations) { 63 return compare(a, b, ignoringAnnotations) <= 0; 64 } 65 66 private static int compare(Node a, Node b, boolean ignoringAnnotations) { 67 if(a.getRange().isPresent() && !b.getRange().isPresent()) { 68 return -1; 69 } 70 if(!a.getRange().isPresent() && b.getRange().isPresent()) { 71 return 1; 72 } 73 if (!a.getRange().isPresent() && !b.getRange().isPresent()) { 74 return 0; 75 } 76 if (ignoringAnnotations) { 77 int signLine = signum(beginLineWithoutConsideringAnnotation(a) - beginLineWithoutConsideringAnnotation(b)); 78 if (signLine == 0) { 79 return signum(beginColumnWithoutConsideringAnnotation(a) - beginColumnWithoutConsideringAnnotation(b)); 80 } else { 81 return signLine; 82 } 83 } 84 85 Position aBegin = a.getBegin().get(); 86 Position bBegin = b.getBegin().get(); 87 88 int signLine = signum(aBegin.line - bBegin.line); 89 if (signLine == 0) { 90 return signum(aBegin.column - bBegin.column); 91 } else { 92 return signLine; 93 } 94 } 95 96 public static AnnotationExpr getLastAnnotation(Node node) { 97 if (node instanceof NodeWithAnnotations) { 98 NodeList<AnnotationExpr> annotations = NodeList.nodeList(((NodeWithAnnotations<?>) node).getAnnotations()); 99 if (annotations.isEmpty()) { 100 return null; 101 } 102 sortByBeginPosition(annotations); 103 return annotations.get(annotations.size() - 1); 104 } else { 105 return null; 106 } 107 } 108 109 private static int beginLineWithoutConsideringAnnotation(Node node) { 110 return beginNodeWithoutConsideringAnnotations(node).getRange().get().begin.line; 111 } 112 113 114 private static int beginColumnWithoutConsideringAnnotation(Node node) { 115 return beginNodeWithoutConsideringAnnotations(node).getRange().get().begin.column; 116 } 117 118 private static Node beginNodeWithoutConsideringAnnotations(Node node) { 119 if (node instanceof MethodDeclaration || node instanceof FieldDeclaration) { 120 NodeWithType<?, Type> casted = (NodeWithType<?, Type>) node; 121 return casted.getType(); 122 } else if (node instanceof ClassOrInterfaceDeclaration) { 123 ClassOrInterfaceDeclaration casted = (ClassOrInterfaceDeclaration) node; 124 return casted.getName(); 125 } else { 126 return node; 127 } 128 } 129 130 public static boolean nodeContains(Node container, Node contained, boolean ignoringAnnotations) { 131 final Range containedRange = contained.getRange().get(); 132 final Range containerRange = container.getRange().get(); 133 if (!ignoringAnnotations || PositionUtils.getLastAnnotation(container) == null) { 134 return container.containsWithin(contained); 135 } 136 if (!container.containsWithin(contained)) { 137 return false; 138 } 139 // if the node is contained, but it comes immediately after the annotations, 140 // let's not consider it contained 141 if (container instanceof NodeWithAnnotations) { 142 int bl = beginLineWithoutConsideringAnnotation(container); 143 int bc = beginColumnWithoutConsideringAnnotation(container); 144 if (bl > containedRange.begin.line) return false; 145 if (bl == containedRange.begin.line && bc > containedRange.begin.column) return false; 146 if (containerRange.end.line < containedRange.end.line) return false; 147 // TODO < or <= ? 148 return !(containerRange.end.line == containedRange.end.line && containerRange.end.column < containedRange.end.column); 149 } 150 return true; 151 } 152 153} 154