• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007-2010 Júlio Vilmar Gesser.
3  * Copyright (C) 2011, 2013-2015 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.ast;
23 
24 import java.util.Iterator;
25 import java.util.LinkedList;
26 import java.util.List;
27 
28 import com.github.javaparser.ast.comments.Comment;
29 import com.github.javaparser.ast.visitor.*;
30 
31 /**
32  * Abstract class for all nodes of the AST.
33  *
34  * Each Node can have one associated comment which describe it and
35  * a number of "orphan comments" which it contains but are not specifically
36  * associated to any element.
37  *
38  * @author Julio Vilmar Gesser
39  */
40 public abstract class Node implements Cloneable {
41 
42     private int beginLine;
43 
44     private int beginColumn;
45 
46     private int endLine;
47 
48     private int endColumn;
49 
50     private Node parentNode;
51 
52     private List<Node> childrenNodes = new LinkedList<Node>();
53     private List<Comment> orphanComments = new LinkedList<Comment>();
54 
55     /**
56      * This attribute can store additional information from semantic analysis.
57      */
58     private Object data;
59 
60     private Comment comment;
61 
Node()62     public Node() {
63     }
64 
Node(final int beginLine, final int beginColumn, final int endLine, final int endColumn)65     public Node(final int beginLine, final int beginColumn, final int endLine, final int endColumn) {
66         this.beginLine = beginLine;
67         this.beginColumn = beginColumn;
68         this.endLine = endLine;
69         this.endColumn = endColumn;
70     }
71 
72     /**
73      * Accept method for visitor support.
74      *
75      * @param <R>
76      *            the type the return value of the visitor
77      * @param <A>
78      *            the type the argument passed to the visitor
79      * @param v
80      *            the visitor implementation
81      * @param arg
82      *            the argument passed to the visitor
83      * @return the result of the visit
84      */
accept(GenericVisitor<R, A> v, A arg)85     public abstract <R, A> R accept(GenericVisitor<R, A> v, A arg);
86 
87     /**
88      * Accept method for visitor support.
89      *
90      * @param <A>
91      *            the type the argument passed for the visitor
92      * @param v
93      *            the visitor implementation
94      * @param arg
95      *            any value relevant for the visitor
96      */
accept(VoidVisitor<A> v, A arg)97     public abstract <A> void accept(VoidVisitor<A> v, A arg);
98 
99     /**
100      * Return the begin column of this node.
101      *
102      * @return the begin column of this node
103      */
getBeginColumn()104     public final int getBeginColumn() {
105         return beginColumn;
106     }
107 
108     /**
109      * Return the begin line of this node.
110      *
111      * @return the begin line of this node
112      */
getBeginLine()113     public final int getBeginLine() {
114         return beginLine;
115     }
116 
117     /**
118      * This is a comment associated with this node.
119      *
120      * @return comment property
121      */
getComment()122     public final Comment getComment() {
123         return comment;
124     }
125 
126     /**
127      * Use this to retrieve additional information associated to this node.
128      *
129      * @return data property
130      */
getData()131     public final Object getData() {
132         return data;
133     }
134 
135     /**
136      * Return the end column of this node.
137      *
138      * @return the end column of this node
139      */
getEndColumn()140     public final int getEndColumn() {
141         return endColumn;
142     }
143 
144     /**
145      * Return the end line of this node.
146      *
147      * @return the end line of this node
148      */
getEndLine()149     public final int getEndLine() {
150         return endLine;
151     }
152 
153     /**
154      * Sets the begin column of this node.
155      *
156      * @param beginColumn
157      *            the begin column of this node
158      */
setBeginColumn(final int beginColumn)159     public final void setBeginColumn(final int beginColumn) {
160         this.beginColumn = beginColumn;
161     }
162 
163     /**
164      * Sets the begin line of this node.
165      *
166      * @param beginLine
167      *            the begin line of this node
168      */
setBeginLine(final int beginLine)169     public final void setBeginLine(final int beginLine) {
170         this.beginLine = beginLine;
171     }
172 
173     /**
174      * Use this to store additional information to this node.
175      *
176      * @param comment to be set
177      */
setComment(final Comment comment)178     public final void setComment(final Comment comment) {
179         if (comment != null && (this instanceof Comment)) {
180             throw new RuntimeException("A comment can not be commented");
181         }
182         if (this.comment != null)
183         {
184             this.comment.setCommentedNode(null);
185         }
186         this.comment = comment;
187         if (comment != null) {
188             this.comment.setCommentedNode(this);
189         }
190     }
191 
192     /**
193      * Use this to store additional information to this node.
194      *
195      * @param data to be set
196      */
setData(final Object data)197     public final void setData(final Object data) {
198         this.data = data;
199     }
200 
201     /**
202      * Sets the end column of this node.
203      *
204      * @param endColumn
205      *            the end column of this node
206      */
setEndColumn(final int endColumn)207     public final void setEndColumn(final int endColumn) {
208         this.endColumn = endColumn;
209     }
210 
211     /**
212      * Sets the end line of this node.
213      *
214      * @param endLine
215      *            the end line of this node
216      */
setEndLine(final int endLine)217     public final void setEndLine(final int endLine) {
218         this.endLine = endLine;
219     }
220 
221     /**
222      * Return the String representation of this node.
223      *
224      * @return the String representation of this node
225      */
226     @Override
toString()227     public final String toString() {
228         final DumpVisitor visitor = new DumpVisitor();
229         accept(visitor, null);
230         return visitor.getSource();
231     }
232 
toStringWithoutComments()233     public final String toStringWithoutComments() {
234         final DumpVisitor visitor = new DumpVisitor(false);
235         accept(visitor, null);
236         return visitor.getSource();
237     }
238 
239     @Override
hashCode()240     public final int hashCode() {
241         return toString().hashCode();
242     }
243 
244     @Override
equals(final Object obj)245     public boolean equals(final Object obj) {
246         if (obj == null || !(obj instanceof Node)) {
247             return false;
248         }
249         return EqualsVisitor.equals(this, (Node) obj);
250     }
251 
252     @Override
clone()253     public Node clone() {
254         return this.accept(new CloneVisitor(), null);
255     }
256 
getParentNode()257     public Node getParentNode() {
258         return parentNode;
259     }
260 
getChildrenNodes()261     public List<Node> getChildrenNodes() {
262         return childrenNodes;
263     }
264 
contains(Node other)265     public boolean contains(Node other) {
266         if (getBeginLine() > other.getBeginLine()) return false;
267         if (getBeginLine() == other.getBeginLine() && getBeginColumn() > other.getBeginColumn()) return false;
268         if (getEndLine() < other.getEndLine()) return false;
269         if (getEndLine() == other.getEndLine() && getEndColumn() < other.getEndColumn()) return false;
270         return true;
271     }
272 
addOrphanComment(Comment comment)273     public void addOrphanComment(Comment comment) {
274         orphanComments.add(comment);
275         comment.setParentNode(this);
276     }
277 
278     /**
279      * This is a list of Comment which are inside the node and are not associated
280      * with any meaningful AST Node.
281      *
282      * For example, comments at the end of methods (immediately before the parenthesis)
283      * or at the end of CompilationUnit are orphan comments.
284      *
285      * When more than one comments preceed a statement, the one immediately preceeding it
286      * it is associated with the statements, while the others are "orphan".
287      * @return all comments that cannot be attributed to a concept
288      */
getOrphanComments()289     public List<Comment> getOrphanComments() {
290         return orphanComments;
291     }
292 
293     /**
294      * This is the list of Comment which are contained in the Node either because
295      * they are properly associated to one of its children or because they are floating
296      * around inside the Node
297      * @return all Comments within the node as a list
298      */
getAllContainedComments()299     public List<Comment> getAllContainedComments() {
300         List<Comment> comments = new LinkedList<Comment>();
301         comments.addAll(getOrphanComments());
302 
303         for (Node child : getChildrenNodes()) {
304             if (child.getComment() != null) {
305                 comments.add(child.getComment());
306             }
307             comments.addAll(child.getAllContainedComments());
308         }
309 
310         return comments;
311     }
312 
313     /**
314      * Assign a new parent to this node, removing it
315      * from the list of children of the previous parent, if any.
316      *
317      * @param parentNode node to be set as parent
318      */
setParentNode(Node parentNode)319     public void setParentNode(Node parentNode) {
320         // remove from old parent, if any
321         if (this.parentNode != null) {
322             this.parentNode.childrenNodes.remove(this);
323         }
324         this.parentNode = parentNode;
325         // add to new parent, if any
326         if (this.parentNode != null) {
327             this.parentNode.childrenNodes.add(this);
328         }
329     }
330 
setAsParentNodeOf(List<? extends Node> childNodes)331     protected void setAsParentNodeOf(List<? extends Node> childNodes) {
332         if (childNodes != null) {
333             Iterator<? extends Node> it = childNodes.iterator();
334             while (it.hasNext()) {
335                 Node current = it.next();
336                 current.setParentNode(this);
337             }
338         }
339     }
340 
setAsParentNodeOf(Node childNode)341     protected void setAsParentNodeOf(Node childNode) {
342         if (childNode != null) {
343             childNode.setParentNode(this);
344         }
345     }
346 
347     public static final int ABSOLUTE_BEGIN_LINE = -1;
348     public static final int ABSOLUTE_END_LINE = -2;
349 
isPositionedAfter(int line, int column)350     public boolean isPositionedAfter(int line, int column) {
351         if (line == ABSOLUTE_BEGIN_LINE) return true;
352         if (getBeginLine() > line) {
353             return true;
354         } else if (getBeginLine() == line) {
355             return getBeginColumn() > column;
356         } else {
357             return false;
358         }
359     }
360 
isPositionedBefore(int line, int column)361     public boolean isPositionedBefore(int line, int column) {
362         if (line == ABSOLUTE_END_LINE) return true;
363         if (getEndLine() < line) {
364             return true;
365         } else if (getEndLine() == line) {
366             return getEndColumn() < column;
367         } else {
368             return false;
369         }
370     }
371 
hasComment()372     public boolean hasComment()
373     {
374         return comment != null;
375     }
376 }
377