KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > core > dom > CompilationUnit


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11
12 package org.eclipse.jdt.core.dom;
13
14 import java.util.ArrayList JavaDoc;
15 import java.util.Arrays JavaDoc;
16 import java.util.Collections JavaDoc;
17 import java.util.List JavaDoc;
18 import java.util.Map JavaDoc;
19
20 import org.eclipse.jdt.core.IJavaElement;
21 import org.eclipse.jdt.core.ITypeRoot;
22 import org.eclipse.jdt.core.compiler.IProblem;
23 import org.eclipse.jdt.internal.compiler.parser.Scanner;
24 import org.eclipse.jdt.internal.compiler.util.Util;
25 import org.eclipse.jface.text.IDocument;
26 import org.eclipse.text.edits.TextEdit;
27
28 /**
29  * Java compilation unit AST node type. This is the type of the root of an AST.
30  * <p>
31  * The source range for this type of node is ordinarily the entire source file,
32  * including leading and trailing whitespace and comments.
33  * </p>
34  * For JLS2:
35  * <pre>
36  * CompilationUnit:
37  * [ PackageDeclaration ]
38  * { ImportDeclaration }
39  * { TypeDeclaration | <b>;</b> }
40  * </pre>
41  * For JLS3, the kinds of type declarations
42  * grew to include enum and annotation type declarations:
43  * <pre>
44  * CompilationUnit:
45  * [ PackageDeclaration ]
46  * { ImportDeclaration }
47  * { TypeDeclaration | EnumDeclaration | AnnotationTypeDeclaration | <b>;</b> }
48  * </pre>
49  *
50  * @since 2.0
51  */

52 public class CompilationUnit extends ASTNode {
53
54     /**
55      * Canonical empty list of messages.
56      */

57     private static final Message[] EMPTY_MESSAGES = new Message[0];
58     
59     /**
60      * Canonical empty list of problems.
61      */

62     private static final IProblem[] EMPTY_PROBLEMS = new IProblem[0];
63     
64     /**
65      * The "imports" structural property of this node type.
66      *
67      * @since 3.0
68      */

69     public static final ChildListPropertyDescriptor IMPORTS_PROPERTY =
70         new ChildListPropertyDescriptor(CompilationUnit.class, "imports", ImportDeclaration.class, NO_CYCLE_RISK); //$NON-NLS-1$
71

72     /**
73      * The "package" structural property of this node type.
74      *
75      * @since 3.0
76      */

77     public static final ChildPropertyDescriptor PACKAGE_PROPERTY =
78         new ChildPropertyDescriptor(CompilationUnit.class, "package", PackageDeclaration.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$
79

80     /**
81      * A list of property descriptors (element type:
82      * {@link StructuralPropertyDescriptor}),
83      * or null if uninitialized.
84      * @since 3.0
85      */

86     private static final List JavaDoc PROPERTY_DESCRIPTORS;
87
88     /**
89      * The "types" structural property of this node type.
90      *
91      * @since 3.0
92      */

93     public static final ChildListPropertyDescriptor TYPES_PROPERTY =
94         new ChildListPropertyDescriptor(CompilationUnit.class, "types", AbstractTypeDeclaration.class, CYCLE_RISK); //$NON-NLS-1$
95

96     static {
97         List JavaDoc properyList = new ArrayList JavaDoc(4);
98         createPropertyList(CompilationUnit.class, properyList);
99         addProperty(PACKAGE_PROPERTY, properyList);
100         addProperty(IMPORTS_PROPERTY, properyList);
101         addProperty(TYPES_PROPERTY, properyList);
102         PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
103     }
104     
105     /**
106      * Returns a list of structural property descriptors for this node type.
107      * Clients must not modify the result.
108      *
109      * @param apiLevel the API level; one of the
110      * <code>AST.JLS*</code> constants
111
112      * @return a list of property descriptors (element type:
113      * {@link StructuralPropertyDescriptor})
114      * @since 3.0
115      */

116     public static List JavaDoc propertyDescriptors(int apiLevel) {
117         return PROPERTY_DESCRIPTORS;
118     }
119     
120     /**
121      * The comment mapper, or <code>null</code> if none;
122      * initially <code>null</code>.
123      * @since 3.0
124      */

125     private DefaultCommentMapper commentMapper = null;
126     
127     /**
128      * The Java type root (an <code>org.eclipse.jdt.core.ICompilationUnit</code> or an <code>org.eclipse.jdt.core.IClassFile</code>)
129      * this compilation unit was created from, or <code>null</code> if it was not created from a Java type root.
130      */

131     private ITypeRoot typeRoot = null;
132     
133     /**
134      * The list of import declarations in textual order order;
135      * initially none (elementType: <code>ImportDeclaration</code>).
136      */

137     private ASTNode.NodeList imports =
138         new ASTNode.NodeList(IMPORTS_PROPERTY);
139     
140     /**
141      * Line end table. If <code>lineEndTable[i] == p</code> then the
142      * line number <code>i+1</code> ends at character position
143      * <code>p</code>. Except for the last line, the positions are that
144      * of the last character of the line delimiter.
145      * For example, the source string <code>A\nB\nC</code> has
146      * line end table {1, 3} (if \n is one character).
147      */

148     private int[] lineEndTable = Util.EMPTY_INT_ARRAY;
149
150     /**
151      * Messages reported by the compiler during parsing or name resolution.
152      */

153     private Message[] messages;
154
155     /**
156      * The comment list (element type: <code>Comment</code>,
157      * or <code>null</code> if none; initially <code>null</code>.
158      * @since 3.0
159      */

160     private List JavaDoc optionalCommentList = null;
161
162     /**
163      * The comment table, or <code>null</code> if none; initially
164      * <code>null</code>. This array is the storage underlying
165      * the <code>optionalCommentList</code> ArrayList.
166      * @since 3.0
167      */

168     Comment[] optionalCommentTable = null;
169     
170     /**
171      * The package declaration, or <code>null</code> if none; initially
172      * <code>null</code>.
173      */

174     private PackageDeclaration optionalPackageDeclaration = null;
175     
176     /**
177      * Problems reported by the compiler during parsing or name resolution.
178      */

179     private IProblem[] problems = EMPTY_PROBLEMS;
180     
181     /**
182      * The list of type declarations in textual order order;
183      * initially none (elementType: <code>AbstractTypeDeclaration</code>)
184      */

185     private ASTNode.NodeList types =
186         new ASTNode.NodeList(TYPES_PROPERTY);
187     
188     /**
189      * Creates a new AST node for a compilation owned by the given AST.
190      * The compilation unit initially has no package declaration, no
191      * import declarations, and no type declarations.
192      * <p>
193      * N.B. This constructor is package-private; all subclasses must be
194      * declared in the same package; clients are unable to declare
195      * additional subclasses.
196      * </p>
197      *
198      * @param ast the AST that is to own this node
199      */

200     CompilationUnit(AST ast) {
201         super(ast);
202     }
203
204     /* (omit javadoc for this method)
205      * Method declared on ASTNode.
206      */

207     void accept0(ASTVisitor visitor) {
208         boolean visitChildren = visitor.visit(this);
209         if (visitChildren) {
210             // visit children in normal left to right reading order
211
acceptChild(visitor, getPackage());
212             acceptChildren(visitor, this.imports);
213             acceptChildren(visitor, this.types);
214         }
215         visitor.endVisit(this);
216     }
217
218     /* (omit javadoc for this method)
219      * Method declared on ASTNode.
220      */

221     ASTNode clone0(AST target) {
222         CompilationUnit result = new CompilationUnit(target);
223         // n.b do not copy line number table or messages
224
result.setSourceRange(this.getStartPosition(), this.getLength());
225         result.setPackage(
226             (PackageDeclaration) ASTNode.copySubtree(target, getPackage()));
227         result.imports().addAll(ASTNode.copySubtrees(target, imports()));
228         result.types().addAll(ASTNode.copySubtrees(target, types()));
229         return result;
230     }
231     
232     
233     /**
234      * Returns the column number corresponding to the given source character
235      * position in the original source string. Column number are zero-based.
236      * Return <code>-1</code> if it is beyond the valid range or <code>-2</code>
237      * if the column number information is unknown.
238      *
239      * @param position a 0-based character position, possibly
240      * negative or out of range
241      * @return the 0-based column number, or <code>-1</code> if the character
242      * position does not correspond to a source line in the original
243      * source file or <code>-2</code> if column number information is unknown for this
244      * compilation unit
245      * @see ASTParser
246      * @since 3.2
247      */

248     public int getColumnNumber(final int position) {
249         if (this.lineEndTable == null) return -2;
250         final int line = getLineNumber(position);
251         if (line == -1) {
252             return -1;
253         }
254         if (line == 1) {
255             if (position >= getStartPosition() + getLength()) return -1;
256             return position;
257         }
258         // length is different from 0
259
int length = this.lineEndTable.length;
260         // -1 to for one-based to zero-based conversion.
261
// -1, again, to get previous line.
262
final int previousLineOffset = this.lineEndTable[line - 2];
263          // previousLineOffset + 1 is the first character of the current line
264
final int offsetForLine = previousLineOffset + 1;
265         final int currentLineEnd = line == length + 1 ? getStartPosition() + getLength() - 1 : this.lineEndTable[line - 1];
266         if (offsetForLine > currentLineEnd) {
267             return -1;
268         } else {
269             return position - offsetForLine;
270         }
271     }
272     
273     /**
274      * Finds the corresponding AST node in the given compilation unit from
275      * which the given binding originated. Returns <code>null</code> if the
276      * binding does not correspond to any node in this compilation unit.
277      * This method always returns <code>null</code> if bindings were not requested
278      * when this AST was built.
279      * <p>
280      * The following table indicates the expected node type for the various
281      * different kinds of bindings:
282      * <ul>
283      * <li>package - a <code>PackageDeclaration</code></li>
284      * <li>class or interface - a <code>TypeDeclaration</code> or a
285      * <code>AnonymousClassDeclaration</code> (for anonymous classes)</li>
286      * <li>primitive type - none</li>
287      * <li>array type - none</li>
288      * <li>field - a <code>VariableDeclarationFragment</code> in a
289      * <code>FieldDeclaration</code> </li>
290      * <li>local variable - a <code>SingleVariableDeclaration</code>, or
291      * a <code>VariableDeclarationFragment</code> in a
292      * <code>VariableDeclarationStatement</code> or
293      * <code>VariableDeclarationExpression</code></li>
294      * <li>method - a <code>MethodDeclaration</code> </li>
295      * <li>constructor - a <code>MethodDeclaration</code> </li>
296      * <li>annotation type - an <code>AnnotationTypeDeclaration</code></li>
297      * <li>annotation type member - an <code>AnnotationTypeMemberDeclaration</code></li>
298      * <li>enum type - an <code>EnumDeclaration</code></li>
299      * <li>enum constant - an <code>EnumConstantDeclaration</code></li>
300      * <li>type variable - a <code>TypeParameter</code></li>
301      * <li>capture binding - none</li>
302      * <li>annotation binding - an <code>Annotation</code></li>
303      * <li>member value pair binding - an <code>MemberValuePair</code>,
304      * or <code>null</code> if it represents a default value or a single member value</li>
305      * </ul>
306      * For parameterized or raw type bindings, the declaring node is
307      * that of the corresponding generic type. And for parameterized or raw
308      * method bindings, the declaring node is that of the corresponding
309      * generic method.
310      * </p>
311      * <p>
312      * Each call to {@link ASTParser#createAST(org.eclipse.core.runtime.IProgressMonitor)} with a request for bindings
313      * gives rise to separate universe of binding objects. This method always returns
314      * <code>null</code> when the binding object comes from a different AST.
315      * Use <code>findDeclaringNode(binding.getKey())</code> when the binding comes
316      * from a different AST.
317      * </p>
318      *
319      * @param binding the binding
320      * @return the corresponding node where the given binding is declared,
321      * or <code>null</code> if the binding does not correspond to a node in this
322      * compilation unit or if bindings were not requested when this AST was built
323      * @see #findDeclaringNode(String)
324      */

325     public ASTNode findDeclaringNode(IBinding binding) {
326         return this.ast.getBindingResolver().findDeclaringNode(binding);
327     }
328     
329     /**
330      * Finds the corresponding AST node in the given compilation unit from
331      * which the binding with the given key originated. Returns
332      * <code>null</code> if the corresponding node cannot be determined.
333      * This method always returns <code>null</code> if bindings were not requested
334      * when this AST was built.
335      * <p>
336      * The following table indicates the expected node type for the various
337      * different kinds of binding keys:
338      * <ul>
339      * <li></li>
340      * <li>package - a <code>PackageDeclaration</code></li>
341      * <li>class or interface - a <code>TypeDeclaration</code> or a
342      * <code>AnonymousClassDeclaration</code> (for anonymous classes)</li>
343      * <li>primitive type - none</li>
344      * <li>array type - none</li>
345      * <li>field - a <code>VariableDeclarationFragment</code> in a
346      * <code>FieldDeclaration</code> </li>
347      * <li>local variable - a <code>SingleVariableDeclaration</code>, or
348      * a <code>VariableDeclarationFragment</code> in a
349      * <code>VariableDeclarationStatement</code> or
350      * <code>VariableDeclarationExpression</code></li>
351      * <li>method - a <code>MethodDeclaration</code> </li>
352      * <li>constructor - a <code>MethodDeclaration</code> </li>
353      * <li>annotation type - an <code>AnnotationTypeDeclaration</code></li>
354      * <li>annotation type member - an <code>AnnotationTypeMemberDeclaration</code></li>
355      * <li>enum type - an <code>EnumDeclaration</code></li>
356      * <li>enum constant - an <code>EnumConstantDeclaration</code></li>
357      * <li>type variable - a <code>TypeParameter</code></li>
358      * <li>capture binding - none</li>
359      * </ul>
360      * For parameterized or raw type bindings, the declaring node is
361      * that of the corresponding generic type. And for parameterized or raw
362      * method bindings, the declaring node is that of the corresponding
363      * generic method.
364      * </p>
365      *
366      * @param key the binding key, or <code>null</code>
367      * @return the corresponding node where a binding with the given
368      * key is declared, or <code>null</code> if the key is <code>null</code>
369      * or if the key does not correspond to a node in this compilation unit
370      * or if bindings were not requested when this AST was built
371      * @see IBinding#getKey()
372      * @since 2.1
373      */

374     public ASTNode findDeclaringNode(String JavaDoc key) {
375         return this.ast.getBindingResolver().findDeclaringNode(key);
376     }
377     
378     /**
379      * Returns a list of the comments encountered while parsing
380      * this compilation unit.
381      * <p>
382      * Since the Java language allows comments to appear most anywhere
383      * in the source text, it is problematic to locate comments in relation
384      * to the structure of an AST. The one exception is doc comments
385      * which, by convention, immediately precede type, field, and
386      * method declarations; these comments are located in the AST
387      * by {@link BodyDeclaration#getJavadoc BodyDeclaration.getJavadoc}.
388      * Other comments do not show up in the AST. The table of comments
389      * is provided for clients that need to find the source ranges of
390      * all comments in the original source string. It includes entries
391      * for comments of all kinds (line, block, and doc), arranged in order
392      * of increasing source position.
393      * </p>
394      * <p>
395      * Note on comment parenting: The {@link ASTNode#getParent() getParent()}
396      * of a doc comment associated with a body declaration is the body
397      * declaration node; for these comment nodes
398      * {@link ASTNode#getRoot() getRoot()} will return the compilation unit
399      * (assuming an unmodified AST) reflecting the fact that these nodes
400      * are property located in the AST for the compilation unit.
401      * However, for other comment nodes, {@link ASTNode#getParent() getParent()}
402      * will return <code>null</code>, and {@link ASTNode#getRoot() getRoot()}
403      * will return the comment node itself, indicating that these comment nodes
404      * are not directly connected to the AST for the compilation unit. The
405      * {@link Comment#getAlternateRoot Comment.getAlternateRoot}
406      * method provides a way to navigate from a comment to its compilation
407      * unit.
408      * </p>
409      * <p>
410      * A note on visitors: The only comment nodes that will be visited when
411      * visiting a compilation unit are the doc comments parented by body
412      * declarations. To visit all comments in normal reading order, iterate
413      * over the comment table and call {@link ASTNode#accept(ASTVisitor) accept}
414      * on each element.
415      * </p>
416      * <p>
417      * Clients cannot modify the resulting list.
418      * </p>
419      *
420      * @return an unmodifiable list of comments in increasing order of source
421      * start position, or <code>null</code> if comment information
422      * for this compilation unit is not available
423      * @see ASTParser
424      * @since 3.0
425      */

426     public List JavaDoc getCommentList() {
427         return this.optionalCommentList;
428     }
429
430     /**
431      * Returns the internal comment mapper.
432      *
433      * @return the comment mapper, or <code>null</code> if none.
434      * @since 3.0
435      */

436     DefaultCommentMapper getCommentMapper() {
437         return this.commentMapper;
438     }
439
440     /**
441      * Returns the extended source length of the given node. Unlike
442      * {@link ASTNode#getStartPosition()} and {@link ASTNode#getLength()},
443      * the extended source range may include comments and whitespace
444      * immediately before or after the normal source range for the node.
445      *
446      * @param node the node
447      * @return a (possibly 0) length, or <code>0</code>
448      * if no source position information is recorded for this node
449      * @see #getExtendedStartPosition(ASTNode)
450      * @since 3.0
451      */

452     public int getExtendedLength(ASTNode node) {
453         if (node == null) {
454             throw new IllegalArgumentException JavaDoc();
455         }
456         if (this.commentMapper == null || node.getAST() != getAST()) {
457             // fall back: use best info available
458
return node.getLength();
459         } else {
460             return this.commentMapper.getExtendedLength(node);
461         }
462     }
463
464     /**
465      * Returns the extended start position of the given node. Unlike
466      * {@link ASTNode#getStartPosition()} and {@link ASTNode#getLength()},
467      * the extended source range may include comments and whitespace
468      * immediately before or after the normal source range for the node.
469      *
470      * @param node the node
471      * @return the 0-based character index, or <code>-1</code>
472      * if no source position information is recorded for this node
473      * @see #getExtendedLength(ASTNode)
474      * @since 3.0
475      */

476     public int getExtendedStartPosition(ASTNode node) {
477         if (node == null) {
478             throw new IllegalArgumentException JavaDoc();
479         }
480         if (this.commentMapper == null || node.getAST() != getAST()) {
481             // fall back: use best info available
482
return node.getStartPosition();
483         } else {
484             return this.commentMapper.getExtendedStartPosition(node);
485         }
486     }
487     
488     /**
489      * The Java element (an <code>org.eclipse.jdt.core.ICompilationUnit</code> or an <code>org.eclipse.jdt.core.IClassFile</code>)
490      * this compilation unit was created from, or <code>null</code> if it was not created from a Java element.
491      *
492      * @return the Java element this compilation unit was created from, or <code>null</code> if none
493      * @since 3.1
494      * @see #getTypeRoot()
495      */

496     public IJavaElement getJavaElement() {
497         return this.typeRoot;
498     }
499     
500     /**
501      * Returns the list of messages reported by the compiler during the parsing
502      * or the type checking of this compilation unit. This list might be a subset of
503      * errors detected and reported by a Java compiler.
504      * <p>
505      * This list of messages is suitable for simple clients that do little
506      * more than log the messages or display them to the user. Clients that
507      * need further details should call <code>getProblems</code> to get
508      * compiler problem objects.
509      * </p>
510      *
511      * @return the list of messages, possibly empty
512      * @see #getProblems()
513      * @see ASTParser
514      */

515     public Message[] getMessages() {
516         if (this.messages == null) {
517             int problemLength = this.problems.length;
518             if (problemLength == 0) {
519                 this.messages = EMPTY_MESSAGES;
520             } else {
521                 this.messages = new Message[problemLength];
522                 for (int i = 0; i < problemLength; i++) {
523                     IProblem problem = this.problems[i];
524                     int start = problem.getSourceStart();
525                     int end = problem.getSourceEnd();
526                     messages[i] = new Message(problem.getMessage(), start, end - start + 1);
527                 }
528             }
529         }
530         return this.messages;
531     }
532
533     /* (omit javadoc for this method)
534      * Method declared on ASTNode.
535      */

536     final int getNodeType0() {
537         return COMPILATION_UNIT;
538     }
539     
540     /**
541      * Returns the node for the package declaration of this compilation
542      * unit, or <code>null</code> if this compilation unit is in the
543      * default package.
544      *
545      * @return the package declaration node, or <code>null</code> if none
546      */

547     public PackageDeclaration getPackage() {
548         return this.optionalPackageDeclaration;
549     }
550     
551     /**
552      * Given a line number and column number, returns the corresponding
553      * position in the original source string.
554      * Returns -2 if no line number information is available for this
555      * compilation unit.
556      * Returns the total size of the source string if <code>line</code>
557      * is greater than the actual number lines in the unit.
558      * Returns -1 if <code>column</code> is less than 0,
559      * or the position of the last character of the line if <code>column</code>
560      * is beyond the legal range, or the given line number is less than one.
561      *
562      * @param line the one-based line number
563      * @param column the zero-based column number
564      * @return the 0-based character position in the source string;
565      * <code>-2</code> if line/column number information is not known
566      * for this compilation unit or <code>-1</code> the inputs are not valid
567      * @since 3.2
568      */

569      public int getPosition(int line, int column) {
570         if (this.lineEndTable == null) return -2;
571         if (line < 1 || column < 0) return -1;
572         int length;
573         if ((length = this.lineEndTable.length) == 0) {
574             if (line != 1) return -1;
575             return column >= getStartPosition() + getLength() ? -1 : column;
576         }
577         if (line == 1) {
578             final int endOfLine = this.lineEndTable[0];
579             return column > endOfLine ? -1 : column;
580         } else if( line > length + 1 ) {
581             // greater than the number of lines in the source string.
582
return -1;
583         }
584         // -1 to for one-based to zero-based conversion.
585
// -1, again, to get previous line.
586
final int previousLineOffset = this.lineEndTable[line - 2];
587          // previousLineOffset + 1 is the first character of the current line
588
final int offsetForLine = previousLineOffset + 1;
589         final int currentLineEnd = line == length + 1 ? getStartPosition() + getLength() - 1 : this.lineEndTable[line-1];
590         if ((offsetForLine + column) > currentLineEnd) {
591             return -1;
592         } else {
593             return offsetForLine + column;
594         }
595     }
596
597     /**
598      * Returns the list of detailed problem reports noted by the compiler
599      * during the parsing or the type checking of this compilation unit. This
600      * list might be a subset of errors detected and reported by a Java
601      * compiler.
602      * <p>
603      * Simple clients that do little more than log the messages or display
604      * them to the user should probably call <code>getMessages</code> instead.
605      * </p>
606      *
607      * @return the list of detailed problem objects, possibly empty
608      * @see #getMessages()
609      * @see ASTParser
610      * @since 2.1
611      */

612     public IProblem[] getProblems() {
613         return this.problems;
614     }
615     
616     /**
617      * The Java type root (a {@link org.eclipse.jdt.core.ICompilationUnit compilation unit} or a {@link org.eclipse.jdt.core.IClassFile class file})
618      * this compilation unit was created from, or <code>null</code> if it was not created from a Java type root.
619      *
620      * @return the Java type root this compilation unit was created from, or <code>null</code> if none
621      * @since 3.3
622      */

623     public ITypeRoot getTypeRoot() {
624         return this.typeRoot;
625     }
626
627     /**
628      * Returns the live list of nodes for the import declarations of this
629      * compilation unit, in order of appearance.
630      *
631      * @return the live list of import declaration nodes
632      * (elementType: <code>ImportDeclaration</code>)
633      */

634     public List JavaDoc imports() {
635         return this.imports;
636     }
637
638     /**
639      * Return the index in the whole comments list {@link #getCommentList() }
640      * of the first leading comments associated with the given node.
641      *
642      * @param node the node
643      * @return 0-based index of first leading comment or -1 if node has no associated
644      * comment before its start position.
645      * @since 3.2
646      */

647     public int firstLeadingCommentIndex(ASTNode node) {
648         if (node == null) {
649             throw new IllegalArgumentException JavaDoc();
650         }
651         if (this.commentMapper == null || node.getAST() != getAST()) {
652             return -1;
653         }
654         return this.commentMapper.firstLeadingCommentIndex(node);
655     }
656
657     /**
658      * Return the index in the whole comments list {@link #getCommentList() }
659      * of the last trailing comments associated with the given node.
660      *
661      * @param node the node
662      * @return 0-based index of last trailing comment or -1 if node has no
663      * associated comment after its end position.
664      * @since 3.2
665      */

666     public int lastTrailingCommentIndex(ASTNode node) {
667         if (node == null) {
668             throw new IllegalArgumentException JavaDoc();
669         }
670         if (this.commentMapper == null || node.getAST() != getAST()) {
671             return -1;
672         }
673         return this.commentMapper.lastTrailingCommentIndex(node);
674     }
675     
676     /**
677      * Initializes the internal comment mapper with the given
678      * scanner.
679      *
680      * @param scanner the scanner
681      * @since 3.0
682      */

683     void initCommentMapper(Scanner scanner) {
684         this.commentMapper = new DefaultCommentMapper(this.optionalCommentTable);
685         this.commentMapper.initialize(this, scanner);
686     }
687
688     /* (omit javadoc for this method)
689      * Method declared on ASTNode.
690      */

691     final List JavaDoc internalGetChildListProperty(ChildListPropertyDescriptor property) {
692         if (property == IMPORTS_PROPERTY) {
693             return imports();
694         }
695         if (property == TYPES_PROPERTY) {
696             return types();
697         }
698         // allow default implementation to flag the error
699
return super.internalGetChildListProperty(property);
700     }
701
702     /* (omit javadoc for this method)
703      * Method declared on ASTNode.
704      */

705     final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
706         if (property == PACKAGE_PROPERTY) {
707             if (get) {
708                 return getPackage();
709             } else {
710                 setPackage((PackageDeclaration) child);
711                 return null;
712             }
713         }
714         // allow default implementation to flag the error
715
return super.internalGetSetChildProperty(property, get, child);
716     }
717
718     /* (omit javadoc for this method)
719      * Method declared on ASTNode.
720      * @since 3.0
721      */

722     final List JavaDoc internalStructuralPropertiesForType(int apiLevel) {
723         return propertyDescriptors(apiLevel);
724     }
725         
726     /**
727      * Returns the line number corresponding to the given source character
728      * position in the original source string. The initial line of the
729      * compilation unit is numbered 1, and each line extends through the
730      * last character of the end-of-line delimiter. The very last line extends
731      * through the end of the source string and has no line delimiter.
732      * For example, the source string <code>class A\n{\n}</code> has 3 lines
733      * corresponding to inclusive character ranges [0,7], [8,9], and [10,10].
734      * Returns 1 for a character position that does not correspond to any
735      * source line, or if no line number information is available for this
736      * compilation unit.
737      *
738      * @param position a 0-based character position, possibly
739      * negative or out of range
740      * @return the 1-based line number, or <code>1</code> if the character
741      * position does not correspond to a source line in the original
742      * source file or if line number information is not known for this
743      * compilation unit
744      * @deprecated Use getLineNumber(int) instead. Be careful to handle the negative values.
745      * @see ASTParser
746      * @see #getLineNumber(int)
747      */

748     public int lineNumber(int position) {
749         int lineNumber = getLineNumber(position);
750         return lineNumber < 1 ? 1 : lineNumber;
751     }
752     
753     /**
754      * Returns the line number corresponding to the given source character
755      * position in the original source string. The initial line of the
756      * compilation unit is numbered 1, and each line extends through the
757      * last character of the end-of-line delimiter. The very last line extends
758      * through the end of the source string and has no line delimiter.
759      * For example, the source string <code>class A\n{\n}</code> has 3 lines
760      * corresponding to inclusive character ranges [0,7], [8,9], and [10,10].
761      * Returns -1 for a character position that does not correspond to any
762      * source line, or -2 if no line number information is available for this
763      * compilation unit.
764      *
765      * @param position a 0-based character position, possibly
766      * negative or out of range
767      * @return the 1-based line number, or <code>-1</code> if the character
768      * position does not correspond to a source line in the original
769      * source file or <code>-2</code> if line number information is not known for this
770      * compilation unit
771      * @see ASTParser
772      * @since 3.2
773      */

774     public int getLineNumber(int position) {
775         if (this.lineEndTable == null) return -2;
776         int length;
777         if ((length = this.lineEndTable.length) == 0) {
778             if (position >= getStartPosition() + getLength()) {
779                 return -1;
780             }
781             return 1;
782         }
783         int low = 0;
784         if (position < 0) {
785             // position illegal
786
return -1;
787         }
788         if (position <= this.lineEndTable[low]) {
789             // before the first line delimiter
790
return 1;
791         }
792         // assert position > lineEndTable[low+1] && low == 0
793
int hi = length - 1;
794         if (position > this.lineEndTable[hi]) {
795             // position beyond the last line separator
796
if (position >= getStartPosition() + getLength()) {
797                 // this is beyond the end of the source length
798
return -1;
799             } else {
800                 return length + 1;
801             }
802         }
803         // assert lineEndTable[low] < position <= lineEndTable[hi]
804
// && low == 0 && hi == length - 1 && low < hi
805

806         // binary search line end table
807
while (true) {
808             // invariant lineEndTable[low] < position <= lineEndTable[hi]
809
// && 0 <= low < hi <= length - 1
810
// reducing measure hi - low
811
if (low + 1 == hi) {
812                 // assert lineEndTable[low] < position <= lineEndTable[low+1]
813
// position is on line low+1 (line number is low+2)
814
return low + 2;
815             }
816             // assert hi - low >= 2, so average is truly in between
817
int mid = low + (hi - low) / 2;
818             // assert 0 <= low < mid < hi <= length - 1
819
if (position <= this.lineEndTable[mid]) {
820                 // assert lineEndTable[low] < position <= lineEndTable[mid]
821
// && 0 <= low < mid < hi <= length - 1
822
hi = mid;
823             } else {
824                 // position > lineEndTable[mid]
825
// assert lineEndTable[mid] < position <= lineEndTable[hi]
826
// && 0 <= low < mid < hi <= length - 1
827
low = mid;
828             }
829             // in both cases, invariant reachieved with reduced measure
830
}
831     }
832
833     /* (omit javadoc for this method)
834      * Method declared on ASTNode.
835      */

836     int memSize() {
837         int size = BASE_NODE_SIZE + 8 * 4;
838         if (this.lineEndTable != null) {
839             size += HEADERS + 4 * this.lineEndTable.length;
840         }
841         if (this.optionalCommentTable != null) {
842             size += HEADERS + 4 * this.optionalCommentTable.length;
843         }
844         // ignore the space taken up by optionalCommentList
845
return size;
846     }
847     
848     /**
849      * Enables the recording of changes to this compilation
850      * unit and its descendents. The compilation unit must have
851      * been created by <code>ASTParser</code> and still be in
852      * its original state. Once recording is on,
853      * arbitrary changes to the subtree rooted at this compilation
854      * unit are recorded internally. Once the modification has
855      * been completed, call <code>rewrite</code> to get an object
856      * representing the corresponding edits to the original
857      * source code string.
858      *
859      * @exception IllegalArgumentException if this compilation unit is
860      * marked as unmodifiable, or if this compilation unit has already
861      * been tampered with, or recording has already been enabled
862      * @since 3.0
863      */

864     public void recordModifications() {
865         getAST().recordModifications(this);
866     }
867
868     /**
869      * Converts all modifications recorded for this compilation
870      * unit into an object representing the corresponding text
871      * edits to the given document containing the original source
872      * code for this compilation unit.
873      * <p>
874      * The compilation unit must have been created by
875      * <code>ASTParser</code> from the source code string in the
876      * given document, and recording must have been turned
877      * on with a prior call to <code>recordModifications</code>
878      * while the AST was still in its original state.
879      * </p>
880      * <p>
881      * Calling this methods does not discard the modifications
882      * on record. Subsequence modifications made to the AST
883      * are added to the ones already on record. If this method
884      * is called again later, the resulting text edit object will
885      * accurately reflect the net cumulative affect of all those
886      * changes.
887      * </p>
888      *
889      * @param document original document containing source code
890      * for this compilation unit
891      * @param options the table of formatter options
892      * (key type: <code>String</code>; value type: <code>String</code>);
893      * or <code>null</code> to use the standard global options
894      * {@link org.eclipse.jdt.core.JavaCore#getOptions() JavaCore.getOptions()}.
895      * @return text edit object describing the changes to the
896      * document corresponding to the recorded AST modifications
897      * @exception IllegalArgumentException if the document passed is
898      * <code>null</code> or does not correspond to this AST
899      * @exception IllegalStateException if <code>recordModifications</code>
900      * was not called to enable recording
901      * @see #recordModifications()
902      * @since 3.0
903      */

904     public TextEdit rewrite(IDocument document, Map JavaDoc options) {
905         return getAST().rewrite(document, options);
906     }
907
908     /**
909      * Sets the list of the comments encountered while parsing
910      * this compilation unit.
911      *
912      * @param commentTable a list of comments in increasing order
913      * of source start position, or <code>null</code> if comment
914      * information for this compilation unit is not available
915      * @exception IllegalArgumentException if the comment table is
916      * not in increasing order of source position
917      * @see #getCommentList()
918      * @see ASTParser
919      * @since 3.0
920      */

921     void setCommentTable(Comment[] commentTable) {
922         // double check table to ensure that all comments have
923
// source positions and are in strictly increasing order
924
if (commentTable == null) {
925             this.optionalCommentList = null;
926             this.optionalCommentTable = null;
927         } else {
928             int nextAvailablePosition = 0;
929             for (int i = 0; i < commentTable.length; i++) {
930                 Comment comment = commentTable[i];
931                 if (comment == null) {
932                     throw new IllegalArgumentException JavaDoc();
933                 }
934                 int start = comment.getStartPosition();
935                 int length = comment.getLength();
936                 if (start < 0 || length < 0 || start < nextAvailablePosition) {
937                     throw new IllegalArgumentException JavaDoc();
938                 }
939                 nextAvailablePosition = comment.getStartPosition() + comment.getLength();
940             }
941             this.optionalCommentTable = commentTable;
942             List JavaDoc commentList = Arrays.asList(commentTable);
943             // protect the list from further modification
944
this.optionalCommentList = Collections.unmodifiableList(commentList);
945         }
946     }
947
948     /**
949      * Sets the Java type root (a {@link org.eclipse.jdt.core.ICompilationUnit compilation unit} or a {@link org.eclipse.jdt.core.IClassFile class file})
950      * this compilation unit was created from, or <code>null</code> if it was not created from a Java type root.
951      *
952      * @param typeRoot the Java type root this compilation unit was created from
953      */

954     void setTypeRoot(ITypeRoot typeRoot) {
955         this.typeRoot = typeRoot;
956     }
957     
958     /**
959      * Sets the line end table for this compilation unit.
960      * If <code>lineEndTable[i] == p</code> then line number <code>i+1</code>
961      * ends at character position <code>p</code>. Except for the last line, the
962      * positions are that of (the last character of) the line delimiter.
963      * For example, the source string <code>A\nB\nC</code> has
964      * line end table {1, 3, 4}.
965      *
966      * @param lineEndTable the line end table
967      */

968     void setLineEndTable(int[] lineEndTable) {
969         if (lineEndTable == null) {
970             throw new NullPointerException JavaDoc();
971         }
972         // alternate root is *not* considered a structural property
973
// but we protect them nevertheless
974
checkModifiable();
975         this.lineEndTable = lineEndTable;
976     }
977     
978     /**
979      * Sets or clears the package declaration of this compilation unit
980      * node to the given package declaration node.
981      *
982      * @param pkgDecl the new package declaration node, or
983      * <code>null</code> if this compilation unit does not have a package
984      * declaration (that is in the default package)
985      * @exception IllegalArgumentException if:
986      * <ul>
987      * <li>the node belongs to a different AST</li>
988      * <li>the node already has a parent</li>
989      * </ul>
990      */

991     public void setPackage(PackageDeclaration pkgDecl) {
992         ASTNode oldChild = this.optionalPackageDeclaration;
993         preReplaceChild(oldChild, pkgDecl, PACKAGE_PROPERTY);
994         this.optionalPackageDeclaration = pkgDecl;
995         postReplaceChild(oldChild, pkgDecl, PACKAGE_PROPERTY);
996     }
997
998
999     /**
1000     * Sets the array of problems reported by the compiler during the parsing or
1001     * name resolution of this compilation unit.
1002     *
1003     * @param problems the list of problems
1004     */

1005    void setProblems(IProblem[] problems) {
1006        if (problems == null) {
1007            throw new IllegalArgumentException JavaDoc();
1008        }
1009        this.problems = problems;
1010    }
1011    
1012    /* (omit javadoc for this method)
1013     * Method declared on ASTNode.
1014     */

1015    final boolean subtreeMatch0(ASTMatcher matcher, Object JavaDoc other) {
1016        // dispatch to correct overloaded match method
1017
return matcher.match(this, other);
1018    }
1019    
1020    /* (omit javadoc for this method)
1021     * Method declared on ASTNode.
1022     */

1023    int treeSize() {
1024        int size = memSize();
1025        if (this.optionalPackageDeclaration != null) {
1026            size += getPackage().treeSize();
1027        }
1028        size += this.imports.listSize();
1029        size += this.types.listSize();
1030        // include disconnected comments
1031
if (this.optionalCommentList != null) {
1032            for (int i = 0; i < this.optionalCommentList.size(); i++) {
1033                Comment comment = (Comment) this.optionalCommentList.get(i);
1034                if (comment != null && comment.getParent() == null) {
1035                    size += comment.treeSize();
1036                }
1037            }
1038        }
1039        return size;
1040    }
1041    
1042    /**
1043     * Returns the live list of nodes for the top-level type declarations of this
1044     * compilation unit, in order of appearance.
1045     * <p>
1046     * Note that in JLS3, the types may include both enum declarations
1047     * and annotation type declarations introduced in J2SE 5.
1048     * For JLS2, the elements are always <code>TypeDeclaration</code>.
1049     * </p>
1050     *
1051     * @return the live list of top-level type declaration
1052     * nodes (elementType: <code>AbstractTypeDeclaration</code>)
1053     */

1054    public List JavaDoc types() {
1055        return this.types;
1056    }
1057}
1058
1059
Popular Tags