1b8ac356ae27165d95d691e177bd8974b7dbb7953Didier Villevalois/*
2b8ac356ae27165d95d691e177bd8974b7dbb7953Didier Villevalois * Copyright (C) 2007-2010 Júlio Vilmar Gesser.
36a40f1d719abd0ecb45240fe0242b2ddf59299e4matozoid * Copyright (C) 2011, 2013-2016 The JavaParser Team.
4b8ac356ae27165d95d691e177bd8974b7dbb7953Didier Villevalois *
5b8ac356ae27165d95d691e177bd8974b7dbb7953Didier Villevalois * This file is part of JavaParser.
676f5dc9d043237e8ada0e6597d6c8d48b67f6d8fFederico Tomassetti *
7edc1e4cc00cc9feceef094cc24c472abffe5aec2Federico Tomassetti * JavaParser can be used either under the terms of
8edc1e4cc00cc9feceef094cc24c472abffe5aec2Federico Tomassetti * a) the GNU Lesser General Public License as published by
9edc1e4cc00cc9feceef094cc24c472abffe5aec2Federico Tomassetti *     the Free Software Foundation, either version 3 of the License, or
10edc1e4cc00cc9feceef094cc24c472abffe5aec2Federico Tomassetti *     (at your option) any later version.
1176f5dc9d043237e8ada0e6597d6c8d48b67f6d8fFederico Tomassetti * b) the terms of the Apache License
12b8ac356ae27165d95d691e177bd8974b7dbb7953Didier Villevalois *
13edc1e4cc00cc9feceef094cc24c472abffe5aec2Federico Tomassetti * You should have received a copy of both licenses in LICENCE.LGPL and
14edc1e4cc00cc9feceef094cc24c472abffe5aec2Federico Tomassetti * LICENCE.APACHE. Please refer to those files for details.
15b8ac356ae27165d95d691e177bd8974b7dbb7953Didier Villevalois *
16b8ac356ae27165d95d691e177bd8974b7dbb7953Didier Villevalois * JavaParser is distributed in the hope that it will be useful,
17b8ac356ae27165d95d691e177bd8974b7dbb7953Didier Villevalois * but WITHOUT ANY WARRANTY; without even the implied warranty of
18b8ac356ae27165d95d691e177bd8974b7dbb7953Didier Villevalois * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19b8ac356ae27165d95d691e177bd8974b7dbb7953Didier Villevalois * GNU Lesser General Public License for more details.
20b8ac356ae27165d95d691e177bd8974b7dbb7953Didier Villevalois */
21482bcecc5d4726b676b208d7efb64572db718cb7matozoid
229985c47e3b2a6ce9b434e787a2a035e2a7aadb4amatozoidpackage com.github.javaparser.utils;
2317229be0bf37d47628d6055ca0252d3f80724590Federico Tomassetti
24fddcb49c8fa1e47ea9a20901d5982619b63fa523matozoidimport com.github.javaparser.Position;
25482bcecc5d4726b676b208d7efb64572db718cb7matozoidimport com.github.javaparser.Range;
26df6c84c0a13f505da7fd0f64626fb5d18fd49619Nicholas Smithimport com.github.javaparser.ast.Node;
27515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggenimport com.github.javaparser.ast.NodeList;
28df6c84c0a13f505da7fd0f64626fb5d18fd49619Nicholas Smithimport com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
29df6c84c0a13f505da7fd0f64626fb5d18fd49619Nicholas Smithimport com.github.javaparser.ast.body.FieldDeclaration;
30df6c84c0a13f505da7fd0f64626fb5d18fd49619Nicholas Smithimport com.github.javaparser.ast.body.MethodDeclaration;
31df6c84c0a13f505da7fd0f64626fb5d18fd49619Nicholas Smithimport com.github.javaparser.ast.expr.AnnotationExpr;
3263eebf8a57420ae4b79550e744624144d9f80570Maximilien CRUZimport com.github.javaparser.ast.nodeTypes.NodeWithAnnotations;
33d7828ee5f27be2f10dda026372898126aeae24b7Danny van Bruggenimport com.github.javaparser.ast.nodeTypes.NodeWithType;
34d7828ee5f27be2f10dda026372898126aeae24b7Danny van Bruggenimport com.github.javaparser.ast.type.Type;
3517229be0bf37d47628d6055ca0252d3f80724590Federico Tomassetti
36fddcb49c8fa1e47ea9a20901d5982619b63fa523matozoidimport java.util.List;
37fddcb49c8fa1e47ea9a20901d5982619b63fa523matozoid
38fddcb49c8fa1e47ea9a20901d5982619b63fa523matozoidimport static java.lang.Integer.signum;
39fddcb49c8fa1e47ea9a20901d5982619b63fa523matozoid
40a9b8b3f9589842f3bef8a48a2f0493e4fe157e65Federico Tomassettipublic final class PositionUtils {
41a9b8b3f9589842f3bef8a48a2f0493e4fe157e65Federico Tomassetti
42a9b8b3f9589842f3bef8a48a2f0493e4fe157e65Federico Tomassetti    private PositionUtils() {
43a9b8b3f9589842f3bef8a48a2f0493e4fe157e65Federico Tomassetti        // prevent instantiation
44a9b8b3f9589842f3bef8a48a2f0493e4fe157e65Federico Tomassetti    }
45ab8df80e3284f5b991b47ae8d3b86f5730900169Federico Tomassetti
46482bcecc5d4726b676b208d7efb64572db718cb7matozoid    public static <T extends Node> void sortByBeginPosition(List<T> nodes) {
47920cc1e1a13d386c73622fce28f05a8d73b1ef51Federico Tomassetti        sortByBeginPosition(nodes, false);
48920cc1e1a13d386c73622fce28f05a8d73b1ef51Federico Tomassetti    }
49920cc1e1a13d386c73622fce28f05a8d73b1ef51Federico Tomassetti
50482bcecc5d4726b676b208d7efb64572db718cb7matozoid    public static <T extends Node> void sortByBeginPosition(NodeList<T> nodes) {
51515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen        sortByBeginPosition(nodes, false);
52515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen    }
53515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen
54482bcecc5d4726b676b208d7efb64572db718cb7matozoid    public static <T extends Node> void sortByBeginPosition(List<T> nodes, final boolean ignoringAnnotations) {
55515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen        nodes.sort((o1, o2) -> PositionUtils.compare(o1, o2, ignoringAnnotations));
56515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen    }
57515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen
58482bcecc5d4726b676b208d7efb64572db718cb7matozoid    public static boolean areInOrder(Node a, Node b) {
59920cc1e1a13d386c73622fce28f05a8d73b1ef51Federico Tomassetti        return areInOrder(a, b, false);
60920cc1e1a13d386c73622fce28f05a8d73b1ef51Federico Tomassetti    }
61920cc1e1a13d386c73622fce28f05a8d73b1ef51Federico Tomassetti
62482bcecc5d4726b676b208d7efb64572db718cb7matozoid    public static boolean areInOrder(Node a, Node b, boolean ignoringAnnotations) {
6324660b3320d659ae17b1ec89d6d351261a507e5dFederico Tomassetti        return compare(a, b, ignoringAnnotations) <= 0;
6424660b3320d659ae17b1ec89d6d351261a507e5dFederico Tomassetti    }
6524660b3320d659ae17b1ec89d6d351261a507e5dFederico Tomassetti
6624660b3320d659ae17b1ec89d6d351261a507e5dFederico Tomassetti    private static int compare(Node a, Node b, boolean ignoringAnnotations) {
67ad9d33b5b22f4f4d470018e41d5c33c1eaf464c8Danny van Bruggen        if(a.getRange().isPresent() && !b.getRange().isPresent()) {
68ad9d33b5b22f4f4d470018e41d5c33c1eaf464c8Danny van Bruggen            return -1;
69ad9d33b5b22f4f4d470018e41d5c33c1eaf464c8Danny van Bruggen        }
70ad9d33b5b22f4f4d470018e41d5c33c1eaf464c8Danny van Bruggen        if(!a.getRange().isPresent() && b.getRange().isPresent()) {
71ad9d33b5b22f4f4d470018e41d5c33c1eaf464c8Danny van Bruggen            return 1;
72ad9d33b5b22f4f4d470018e41d5c33c1eaf464c8Danny van Bruggen        }
73ad9d33b5b22f4f4d470018e41d5c33c1eaf464c8Danny van Bruggen        if (!a.getRange().isPresent() && !b.getRange().isPresent()) {
74a2152a8282754017f1c2d1eb5b45cfde7e89950bDanny van Bruggen            return 0;
753c7fefbf66b94c5c7b416472d416a54651b52122Danny van Bruggen        }
76920cc1e1a13d386c73622fce28f05a8d73b1ef51Federico Tomassetti        if (ignoringAnnotations) {
774eb0569c40debb8dd96aeb72ef24ae8ff39f579bFederico Tomassetti            int signLine = signum(beginLineWithoutConsideringAnnotation(a) - beginLineWithoutConsideringAnnotation(b));
7824660b3320d659ae17b1ec89d6d351261a507e5dFederico Tomassetti            if (signLine == 0) {
794eb0569c40debb8dd96aeb72ef24ae8ff39f579bFederico Tomassetti                return signum(beginColumnWithoutConsideringAnnotation(a) - beginColumnWithoutConsideringAnnotation(b));
8024660b3320d659ae17b1ec89d6d351261a507e5dFederico Tomassetti            } else {
8124660b3320d659ae17b1ec89d6d351261a507e5dFederico Tomassetti                return signLine;
8224660b3320d659ae17b1ec89d6d351261a507e5dFederico Tomassetti            }
83920cc1e1a13d386c73622fce28f05a8d73b1ef51Federico Tomassetti        }
84920cc1e1a13d386c73622fce28f05a8d73b1ef51Federico Tomassetti
85d679ae1e9f30f5d7cc29e510d8b7a60593f2c0fdDanny van Bruggen        Position aBegin = a.getBegin().get();
86d679ae1e9f30f5d7cc29e510d8b7a60593f2c0fdDanny van Bruggen        Position bBegin = b.getBegin().get();
87fddcb49c8fa1e47ea9a20901d5982619b63fa523matozoid
88fddcb49c8fa1e47ea9a20901d5982619b63fa523matozoid        int signLine = signum(aBegin.line - bBegin.line);
8924660b3320d659ae17b1ec89d6d351261a507e5dFederico Tomassetti        if (signLine == 0) {
90fddcb49c8fa1e47ea9a20901d5982619b63fa523matozoid            return signum(aBegin.column - bBegin.column);
9124660b3320d659ae17b1ec89d6d351261a507e5dFederico Tomassetti        } else {
9224660b3320d659ae17b1ec89d6d351261a507e5dFederico Tomassetti            return signLine;
9324660b3320d659ae17b1ec89d6d351261a507e5dFederico Tomassetti        }
9417229be0bf37d47628d6055ca0252d3f80724590Federico Tomassetti    }
95ab8df80e3284f5b991b47ae8d3b86f5730900169Federico Tomassetti
96920cc1e1a13d386c73622fce28f05a8d73b1ef51Federico Tomassetti    public static AnnotationExpr getLastAnnotation(Node node) {
97482bcecc5d4726b676b208d7efb64572db718cb7matozoid        if (node instanceof NodeWithAnnotations) {
98515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen            NodeList<AnnotationExpr> annotations = NodeList.nodeList(((NodeWithAnnotations<?>) node).getAnnotations());
99482bcecc5d4726b676b208d7efb64572db718cb7matozoid            if (annotations.isEmpty()) {
100920cc1e1a13d386c73622fce28f05a8d73b1ef51Federico Tomassetti                return null;
101920cc1e1a13d386c73622fce28f05a8d73b1ef51Federico Tomassetti            }
102920cc1e1a13d386c73622fce28f05a8d73b1ef51Federico Tomassetti            sortByBeginPosition(annotations);
103482bcecc5d4726b676b208d7efb64572db718cb7matozoid            return annotations.get(annotations.size() - 1);
104920cc1e1a13d386c73622fce28f05a8d73b1ef51Federico Tomassetti        } else {
105920cc1e1a13d386c73622fce28f05a8d73b1ef51Federico Tomassetti            return null;
106920cc1e1a13d386c73622fce28f05a8d73b1ef51Federico Tomassetti        }
107920cc1e1a13d386c73622fce28f05a8d73b1ef51Federico Tomassetti    }
108920cc1e1a13d386c73622fce28f05a8d73b1ef51Federico Tomassetti
109920cc1e1a13d386c73622fce28f05a8d73b1ef51Federico Tomassetti    private static int beginLineWithoutConsideringAnnotation(Node node) {
1103c7fefbf66b94c5c7b416472d416a54651b52122Danny van Bruggen        return beginNodeWithoutConsideringAnnotations(node).getRange().get().begin.line;
111920cc1e1a13d386c73622fce28f05a8d73b1ef51Federico Tomassetti    }
112920cc1e1a13d386c73622fce28f05a8d73b1ef51Federico Tomassetti
113920cc1e1a13d386c73622fce28f05a8d73b1ef51Federico Tomassetti
114920cc1e1a13d386c73622fce28f05a8d73b1ef51Federico Tomassetti    private static int beginColumnWithoutConsideringAnnotation(Node node) {
1153c7fefbf66b94c5c7b416472d416a54651b52122Danny van Bruggen        return beginNodeWithoutConsideringAnnotations(node).getRange().get().begin.column;
116920cc1e1a13d386c73622fce28f05a8d73b1ef51Federico Tomassetti    }
117920cc1e1a13d386c73622fce28f05a8d73b1ef51Federico Tomassetti
118920cc1e1a13d386c73622fce28f05a8d73b1ef51Federico Tomassetti    private static Node beginNodeWithoutConsideringAnnotations(Node node) {
11934898f09a47675498ea38d7494cd7b2d29136570Ross Allan        if (node instanceof MethodDeclaration || node instanceof FieldDeclaration) {
120a8f6c6d62fcbdc3506f19f11a7b89307cbf4c515Danny van Bruggen            NodeWithType<?, Type> casted = (NodeWithType<?, Type>) node;
121d7828ee5f27be2f10dda026372898126aeae24b7Danny van Bruggen            return casted.getType();
122920cc1e1a13d386c73622fce28f05a8d73b1ef51Federico Tomassetti        } else if (node instanceof ClassOrInterfaceDeclaration) {
123920cc1e1a13d386c73622fce28f05a8d73b1ef51Federico Tomassetti            ClassOrInterfaceDeclaration casted = (ClassOrInterfaceDeclaration) node;
12402b3c5e03c44a9373c3a9d323c3425bdffade688Danny van Bruggen            return casted.getName();
125482bcecc5d4726b676b208d7efb64572db718cb7matozoid        } else {
126920cc1e1a13d386c73622fce28f05a8d73b1ef51Federico Tomassetti            return node;
127920cc1e1a13d386c73622fce28f05a8d73b1ef51Federico Tomassetti        }
128920cc1e1a13d386c73622fce28f05a8d73b1ef51Federico Tomassetti    }
129920cc1e1a13d386c73622fce28f05a8d73b1ef51Federico Tomassetti
130482bcecc5d4726b676b208d7efb64572db718cb7matozoid    public static boolean nodeContains(Node container, Node contained, boolean ignoringAnnotations) {
1313c7fefbf66b94c5c7b416472d416a54651b52122Danny van Bruggen        final Range containedRange = contained.getRange().get();
1323c7fefbf66b94c5c7b416472d416a54651b52122Danny van Bruggen        final Range containerRange = container.getRange().get();
133482bcecc5d4726b676b208d7efb64572db718cb7matozoid        if (!ignoringAnnotations || PositionUtils.getLastAnnotation(container) == null) {
134515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen            return container.containsWithin(contained);
135920cc1e1a13d386c73622fce28f05a8d73b1ef51Federico Tomassetti        }
136482bcecc5d4726b676b208d7efb64572db718cb7matozoid        if (!container.containsWithin(contained)) {
137920cc1e1a13d386c73622fce28f05a8d73b1ef51Federico Tomassetti            return false;
138920cc1e1a13d386c73622fce28f05a8d73b1ef51Federico Tomassetti        }
139920cc1e1a13d386c73622fce28f05a8d73b1ef51Federico Tomassetti        // if the node is contained, but it comes immediately after the annotations,
140920cc1e1a13d386c73622fce28f05a8d73b1ef51Federico Tomassetti        // let's not consider it contained
141482bcecc5d4726b676b208d7efb64572db718cb7matozoid        if (container instanceof NodeWithAnnotations) {
142920cc1e1a13d386c73622fce28f05a8d73b1ef51Federico Tomassetti            int bl = beginLineWithoutConsideringAnnotation(container);
143920cc1e1a13d386c73622fce28f05a8d73b1ef51Federico Tomassetti            int bc = beginColumnWithoutConsideringAnnotation(container);
144482bcecc5d4726b676b208d7efb64572db718cb7matozoid            if (bl > containedRange.begin.line) return false;
145482bcecc5d4726b676b208d7efb64572db718cb7matozoid            if (bl == containedRange.begin.line && bc > containedRange.begin.column) return false;
146482bcecc5d4726b676b208d7efb64572db718cb7matozoid            if (containerRange.end.line < containedRange.end.line) return false;
14733299776265b9acd160a5196cb9306fd9a7085ecmatozoid            // TODO < or <= ?
148482bcecc5d4726b676b208d7efb64572db718cb7matozoid            return !(containerRange.end.line == containedRange.end.line && containerRange.end.column < containedRange.end.column);
149920cc1e1a13d386c73622fce28f05a8d73b1ef51Federico Tomassetti        }
150920cc1e1a13d386c73622fce28f05a8d73b1ef51Federico Tomassetti        return true;
151920cc1e1a13d386c73622fce28f05a8d73b1ef51Federico Tomassetti    }
152920cc1e1a13d386c73622fce28f05a8d73b1ef51Federico Tomassetti
15317229be0bf37d47628d6055ca0252d3f80724590Federico Tomassetti}
154