Home | History | Annotate | Download | only in utils
      1 /*
      2  * Copyright (C) 2007-2010 Jlio 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 
     22 package com.github.javaparser.utils;
     23 
     24 import com.github.javaparser.Position;
     25 import com.github.javaparser.Range;
     26 import com.github.javaparser.ast.Node;
     27 import com.github.javaparser.ast.NodeList;
     28 import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
     29 import com.github.javaparser.ast.body.FieldDeclaration;
     30 import com.github.javaparser.ast.body.MethodDeclaration;
     31 import com.github.javaparser.ast.expr.AnnotationExpr;
     32 import com.github.javaparser.ast.nodeTypes.NodeWithAnnotations;
     33 import com.github.javaparser.ast.nodeTypes.NodeWithType;
     34 import com.github.javaparser.ast.type.Type;
     35 
     36 import java.util.List;
     37 
     38 import static java.lang.Integer.signum;
     39 
     40 public 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