Node.java revision 9528039468accca4734ee3b35670bd1d52369e4c
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 22package com.github.javaparser.ast; 23 24import java.util.Iterator; 25import java.util.LinkedList; 26import java.util.List; 27 28import com.github.javaparser.ast.comments.Comment; 29import 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 */ 40public 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 62 public Node() { 63 } 64 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 227 public final String toString() { 228 final DumpVisitor visitor = new DumpVisitor(); 229 accept(visitor, null); 230 return visitor.getSource(); 231 } 232 233 public final String toStringWithoutComments() { 234 final DumpVisitor visitor = new DumpVisitor(false); 235 accept(visitor, null); 236 return visitor.getSource(); 237 } 238 239 @Override 240 public final int hashCode() { 241 return toString().hashCode(); 242 } 243 244 @Override 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 253 public Node clone() { 254 return this.accept(new CloneVisitor(), null); 255 } 256 257 public Node getParentNode() { 258 return parentNode; 259 } 260 261 public List<Node> getChildrenNodes() { 262 return childrenNodes; 263 } 264 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 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 */ 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 */ 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 */ 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 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 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 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 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 372 public boolean hasComment() 373 { 374 return comment != null; 375 } 376} 377