KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*******************************************************************************
2  * Copyright (c) 2004, 2007 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 package org.eclipse.jdt.core.dom;
12
13 import org.eclipse.jdt.core.compiler.CharOperation;
14 import org.eclipse.jdt.core.compiler.InvalidInputException;
15 import org.eclipse.jdt.internal.compiler.parser.Scanner;
16 import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
17 import org.eclipse.jdt.internal.compiler.util.Util;
18
19 /**
20  * Internal class for associating comments with AST nodes.
21  *
22  * @since 3.0
23  */

24 class DefaultCommentMapper {
25     Comment[] comments;
26     Scanner scanner;
27     
28     // extended nodes storage
29
int leadingPtr;
30     ASTNode[] leadingNodes;
31     long[] leadingIndexes;
32     int trailingPtr, lastTrailingPtr;
33     ASTNode[] trailingNodes;
34     long[] trailingIndexes;
35     static final int STORAGE_INCREMENT = 16;
36
37     /**
38      * @param table the given table of comments
39      */

40     DefaultCommentMapper(Comment[] table) {
41         this.comments = table;
42     }
43
44     boolean hasSameTable(Comment[] table) {
45         return this.comments == table;
46     }
47
48     /**
49      * Get comment of the list which includes a given position
50      *
51      * @param position The position belonging to the looked up comment
52      * @return comment which includes the given position or null if none was found
53      */

54     Comment getComment(int position) {
55
56         if (this.comments == null) {
57             return null;
58         }
59         int size = this.comments.length;
60         if (size == 0) {
61             return null;
62         }
63         int index = getCommentIndex(0, position, 0);
64         if (index<0) {
65             return null;
66         }
67         return this.comments[index];
68     }
69
70     /*
71      * Get the index of comment which contains given position.
72      * If there's no matching comment, then return depends on exact parameter:
73      * = 0: return -1
74      * < 0: return index of the comment before the given position
75      * > 0: return index of the comment after the given position
76      */

77     private int getCommentIndex(int start, int position, int exact) {
78         if (position == 0) {
79             if (this.comments.length > 0 && this.comments[0].getStartPosition() == 0) {
80                 return 0;
81             }
82             return -1;
83         }
84         int bottom = start, top = this.comments.length - 1;
85         int i = 0, index = -1;
86         Comment comment = null;
87         while (bottom <= top) {
88             i = bottom + (top - bottom) /2;
89             comment = this.comments[i];
90             int commentStart = comment.getStartPosition();
91             if (position < commentStart) {
92                 top = i-1;
93             } else if (position >=(commentStart+comment.getLength())) {
94                 bottom = i+1;
95             } else {
96                 index = i;
97                 break;
98             }
99         }
100         if (index<0 && exact!=0) {
101             comment = this.comments[i];
102             if (position < comment.getStartPosition()) {
103                 return exact<0 ? i-1 : i;
104             } else {
105                 return exact<0 ? i : i+1;
106             }
107         }
108         return index;
109     }
110
111     /**
112      * Returns the extended start position of the given node. Unlike
113      * {@link ASTNode#getStartPosition()} and {@link ASTNode#getLength()},
114      * the extended source range may include comments and whitespace
115      * immediately before or after the normal source range for the node.
116      *
117      * @param node the node
118      * @return the 0-based character index, or <code>-1</code>
119      * if no source position information is recorded for this node
120      * @see #getExtendedLength(ASTNode)
121      * @since 3.0
122      */

123     public int getExtendedStartPosition(ASTNode node) {
124         if (this.leadingPtr >= 0) {
125             long range = -1;
126             for (int i=0; range<0 && i<=this.leadingPtr; i++) {
127                 if (this.leadingNodes[i] == node) range = this.leadingIndexes[i];
128             }
129             if (range >= 0) {
130                 return this.comments[(int)(range>>32)].getStartPosition() ;
131             }
132         }
133         return node.getStartPosition();
134     }
135
136     /*
137      * Search the line number corresponding to a specific position
138      * between the given line range (inclusive)
139      * @param position int
140      * @parem lineRange size-2 int[]
141      * @return int
142      */

143     public final int getLineNumber(int position, int[] lineRange) {
144         int[] lineEnds = this.scanner.lineEnds;
145         int length = lineEnds.length;
146         return Util.getLineNumber(position, lineEnds, (lineRange[0] > length ? length : lineRange[0]) -1, (lineRange[1] > length ? length : lineRange[1]) - 1);
147     }
148
149     /*
150      * Returns the extended end position of the given node.
151      */

152     public int getExtendedEnd(ASTNode node) {
153         int end = node.getStartPosition() + node.getLength();
154         if (this.trailingPtr >= 0) {
155             long range = -1;
156             for (int i=0; range<0 && i<=this.trailingPtr; i++) {
157                 if (this.trailingNodes[i] == node) range = this.trailingIndexes[i];
158             }
159             if (range >= 0) {
160                 Comment lastComment = this.comments[(int) range];
161                 end = lastComment.getStartPosition() + lastComment.getLength();
162             }
163         }
164         return end-1;
165     }
166
167     /**
168      * Returns the extended source length of the given node. Unlike
169      * {@link ASTNode#getStartPosition()} and {@link ASTNode#getLength()},
170      * the extended source range may include comments and whitespace
171      * immediately before or after the normal source range for the node.
172      *
173      * @param node the node
174      * @return a (possibly 0) length, or <code>0</code>
175      * if no source position information is recorded for this node
176      * @see #getExtendedStartPosition(ASTNode)
177      * @see #getExtendedEnd(ASTNode)
178      * @since 3.0
179      */

180     public int getExtendedLength(ASTNode node) {
181         return getExtendedEnd(node) - getExtendedStartPosition(node) + 1;
182     }
183
184     /**
185      * Return index of first leading comment of a given node.
186      *
187      * @param node
188      * @return index of first leading comment or -1 if node has no leading comment
189      */

190     int firstLeadingCommentIndex(ASTNode node) {
191         if (this.leadingPtr >= 0) {
192             for (int i=0; i<=this.leadingPtr; i++) {
193                 if (this.leadingNodes[i] == node) {
194                     return (int) (this.leadingIndexes[i]>>32);
195                 }
196             }
197         }
198         return -1;
199     }
200
201     /**
202      * Return index of last trailing comment of a given node.
203      *
204      * @param node
205      * @return index of last trailing comment or -1 if node has no trailing comment
206      */

207     int lastTrailingCommentIndex(ASTNode node) {
208         if (this.trailingPtr >= 0) {
209             for (int i=0; i<=this.trailingPtr; i++) {
210                 if (this.trailingNodes[i] == node) {
211                     return (int) this.trailingIndexes[i];
212                 }
213             }
214         }
215         return -1;
216     }
217
218     /*
219      * Initialize leading and trailing comments tables in whole nodes hierarchy of a compilation
220      * unit.
221      * Scanner is necessary to scan between nodes and comments and verify if there's
222      * nothing else than white spaces.
223      */

224     void initialize(CompilationUnit unit, Scanner sc) {
225
226         // Init array pointers
227
this.leadingPtr = -1;
228         this.trailingPtr = -1;
229     
230         // Init comments
231
this.comments = unit.optionalCommentTable;
232         if (this.comments == null) {
233             return;
234         }
235         int size = this.comments.length;
236         if (size == 0) {
237             return;
238         }
239
240         // Init scanner and start ranges computing
241
this.scanner = sc;
242         this.scanner.tokenizeWhiteSpace = true;
243
244         // Start unit visit
245
DefaultASTVisitor commentVisitor = new CommentMapperVisitor();
246         unit.accept(commentVisitor);
247         
248         // Reduce leading arrays if necessary
249
int leadingCount = this.leadingPtr + 1;
250         if (leadingCount > 0 && leadingCount < this.leadingIndexes.length) {
251             System.arraycopy(this.leadingNodes, 0, this.leadingNodes = new ASTNode[leadingCount], 0, leadingCount);
252             System.arraycopy(this.leadingIndexes, 0, this.leadingIndexes= new long[leadingCount], 0, leadingCount);
253         }
254         
255         // Reduce trailing arrays if necessary
256
if (this.trailingPtr >= 0) {
257             // remove last remaining unresolved nodes
258
while (this.trailingIndexes[this.trailingPtr] == -1) {
259                 this.trailingPtr--;
260                 if (this.trailingPtr < 0) {
261                     this.trailingIndexes = null;
262                     this.trailingNodes = null;
263                     break;
264                 }
265             }
266
267             // reduce array size
268
int trailingCount = this.trailingPtr + 1;
269             if (trailingCount > 0 && trailingCount < this.trailingIndexes.length) {
270                 System.arraycopy(this.trailingNodes, 0, this.trailingNodes = new ASTNode[trailingCount], 0, trailingCount);
271                 System.arraycopy(this.trailingIndexes, 0, this.trailingIndexes= new long[trailingCount], 0, trailingCount);
272             }
273         }
274
275         // Release scanner as it's only used during unit visit
276
this.scanner = null;
277     }
278
279     /**
280      * Search and store node leading comments. Comments are searched in position range
281      * from previous extended position to node start position. If one or several comment are found,
282      * returns first comment start position, otherwise returns node start position.
283      * <p>
284      * Starts to search for first comment before node start position and return if none was found...
285      *</p><p>
286      * When first comment is found before node, goes up in comment list until one of
287      * following conditions becomes true:
288      * <ol>
289      * <li>comment end is before previous end</li>
290      * <li>comment start and previous end is on the same line but not on same line of node start</li>
291      * <li>there's other than white characters between current node and comment</li>
292      * <li>there's more than 1 line between current node and comment</li>
293      * </ol>
294      * If some comment have been found, then no token should be on
295      * on the same line before, so remove all comments which do not verify this assumption.
296      * </p><p>
297      * If finally there's leading still comments, then stores indexes of the first and last one
298      * in leading comments table.
299      */

300     int storeLeadingComments(ASTNode node, int previousEnd, int[] parentLineRange) {
301         // Init extended position
302
int nodeStart = node.getStartPosition();
303         int extended = nodeStart;
304         
305         // Get line of node start position
306
int previousEndLine = getLineNumber(previousEnd, parentLineRange);
307         int nodeStartLine = getLineNumber(nodeStart, parentLineRange);
308         
309         // Find first comment index
310
int idx = getCommentIndex(0, nodeStart, -1);
311         if (idx == -1) {
312             return nodeStart;
313         }
314         
315         // Look after potential comments
316
int startIdx = -1;
317         int endIdx = idx;
318         int previousStart = nodeStart;
319         while (idx >= 0 && previousStart >= previousEnd) {
320             // Verify for each comment that there's only white spaces between end and start of {following comment|node}
321
Comment comment = this.comments[idx];
322             int commentStart = comment.getStartPosition();
323             int end = commentStart+comment.getLength()-1;
324             int commentLine = getLineNumber(commentStart, parentLineRange);
325             if (end <= previousEnd || (commentLine == previousEndLine && commentLine != nodeStartLine)) {
326                 // stop search on condition 1) and 2)
327
break;
328             } else if ((end+1) < previousStart) { // may be equals => then no scan is necessary
329
this.scanner.resetTo(end+1, previousStart);
330                 try {
331                     int token = this.scanner.getNextToken();
332                     if (token != TerminalTokens.TokenNameWHITESPACE || this.scanner.currentPosition != previousStart) {
333                         // stop search on condition 3)
334
// if first comment fails, then there's no extended position in fact
335
if (idx == endIdx) {
336                             return nodeStart;
337                         }
338                         break;
339                     }
340                 } catch (InvalidInputException e) {
341                     // Should not happen, but return no extended position...
342
return nodeStart;
343                 }
344                 // verify that there's no more than one line between node/comments
345
char[] gap = this.scanner.getCurrentIdentifierSource();
346                 int nbrLine = 0;
347                 int pos = -1;
348                 while ((pos=CharOperation.indexOf('\n', gap,pos+1)) >= 0) {
349                     nbrLine++;
350                 }
351                 if (nbrLine > 1) {
352                     // stop search on condition 4)
353
break;
354                 }
355             }
356             // Store previous infos
357
previousStart = commentStart;
358             startIdx = idx--;
359         }
360         if (startIdx != -1) {
361             // Verify that there's no token on the same line before first leading comment
362
int commentStart = this.comments[startIdx].getStartPosition();
363             if (previousEnd < commentStart && previousEndLine != nodeStartLine) {
364                 int lastTokenEnd = previousEnd;
365                 this.scanner.resetTo(previousEnd, commentStart);
366                 try {
367                     while (this.scanner.currentPosition < commentStart) {
368                         if (this.scanner.getNextToken() != TerminalTokens.TokenNameWHITESPACE) {
369                             lastTokenEnd = this.scanner.getCurrentTokenEndPosition();
370                         }
371                     }
372                 } catch (InvalidInputException e) {
373                     // do nothing
374
}
375                 int lastTokenLine = getLineNumber(lastTokenEnd, parentLineRange);
376                 int length = this.comments.length;
377                 while (startIdx<length && lastTokenLine == getLineNumber(this.comments[startIdx].getStartPosition(), parentLineRange) && nodeStartLine != lastTokenLine) {
378                     startIdx++;
379                 }
380             }
381             // Store leading comments indexes
382
if (startIdx <= endIdx) {
383                 if (++this.leadingPtr == 0) {
384                     this.leadingNodes = new ASTNode[STORAGE_INCREMENT];
385                     this.leadingIndexes = new long[STORAGE_INCREMENT];
386                 } else if (this.leadingPtr == this.leadingNodes.length) {
387                     int newLength = (this.leadingPtr*3/2)+STORAGE_INCREMENT;
388                     System.arraycopy(this.leadingNodes, 0, this.leadingNodes = new ASTNode[newLength], 0, this.leadingPtr);
389                     System.arraycopy(this.leadingIndexes, 0, this.leadingIndexes = new long[newLength], 0, this.leadingPtr);
390                 }
391                 this.leadingNodes[this.leadingPtr] = node;
392                 this.leadingIndexes[this.leadingPtr] = (((long)startIdx)<<32) + endIdx;
393                 extended = this.comments[endIdx].getStartPosition();
394             }
395         }
396         return extended;
397     }
398
399     /**
400      * Search and store node trailing comments. Comments are searched in position range
401      * from node end position to specified next start. If one or several comment are found,
402      * returns last comment end position, otherwise returns node end position.
403      * <p>
404      * Starts to search for first comment after node end position and return if none was found...
405      *</p><p>
406      * When first comment is found after node, goes down in comment list until one of
407      * following conditions becomes true:
408      * <ol>
409      * <li>comment start is after next start</li>
410      * <li>there's other than white characters between current node and comment</li>
411      * <li>there's more than 1 line between current node and comment</li>
412      *</ol>
413      * If at least potential comments have been found, then all of them has to be separated
414      * from following node. So, remove all comments which do not verify this assumption.
415      * Note that this verification is not applicable on last node.
416      * </p><p>
417      * If finally there's still trailing comments, then stores indexes of the first and last one
418      * in trailing comments table.
419      */

420     int storeTrailingComments(ASTNode node, int nextStart, boolean lastChild, int[] parentLineRange) {
421
422         // Init extended position
423
int nodeEnd = node.getStartPosition()+node.getLength()-1;
424         if (nodeEnd == nextStart) {
425             // special case for last child of its parent
426
if (++this.trailingPtr == 0) {
427                 this.trailingNodes = new ASTNode[STORAGE_INCREMENT];
428                 this.trailingIndexes = new long[STORAGE_INCREMENT];
429                 this.lastTrailingPtr = -1;
430             } else if (this.trailingPtr == this.trailingNodes.length) {
431                 int newLength = (this.trailingPtr*3/2)+STORAGE_INCREMENT;
432                 System.arraycopy(this.trailingNodes, 0, this.trailingNodes = new ASTNode[newLength], 0, this.trailingPtr);
433                 System.arraycopy(this.trailingIndexes, 0, this.trailingIndexes = new long[newLength], 0, this.trailingPtr);
434             }
435             this.trailingNodes[this.trailingPtr] = node;
436             this.trailingIndexes[this.trailingPtr] = -1;
437             return nodeEnd;
438         }
439         int extended = nodeEnd;
440         
441         // Get line number
442
int nodeEndLine = getLineNumber(nodeEnd, parentLineRange);
443         
444         // Find comments range index
445
int idx = getCommentIndex(0, nodeEnd, 1);
446         if (idx == -1) {
447             return nodeEnd;
448         }
449
450         // Look after potential comments
451
int startIdx = idx;
452         int endIdx = -1;
453         int length = this.comments.length;
454         int commentStart = extended+1;
455         int previousEnd = nodeEnd+1;
456         int sameLineIdx = -1;
457         while (idx<length && commentStart < nextStart) {
458             // get comment and leave if next starting position has been reached
459
Comment comment = this.comments[idx];
460             commentStart = comment.getStartPosition();
461             // verify that there's nothing else than white spaces between node/comments
462
if (commentStart >= nextStart) {
463                 // stop search on condition 1)
464
break;
465             } else if (previousEnd < commentStart) {
466                 this.scanner.resetTo(previousEnd, commentStart);
467                 try {
468                     int token = this.scanner.getNextToken();
469                     if (token != TerminalTokens.TokenNameWHITESPACE || this.scanner.currentPosition != commentStart) {
470                         // stop search on condition 2)
471
// if first index fails, then there's no extended position in fact...
472
if (idx == startIdx) {
473                             return nodeEnd;
474                         }
475                         // otherwise we get the last index of trailing comment => break
476
break;
477                     }
478                 } catch (InvalidInputException e) {
479                     // Should not happen, but return no extended position...
480
return nodeEnd;
481                 }
482                 // verify that there's no more than one line between node/comments
483
char[] gap = this.scanner.getCurrentIdentifierSource();
484                 int nbrLine = 0;
485                 int pos = -1;
486                 while ((pos=CharOperation.indexOf('\n', gap,pos+1)) >= 0) {
487                     nbrLine++;
488                 }
489                 if (nbrLine > 1) {
490                     // stop search on condition 3)
491
break;
492                 }
493             }
494             // Store index if we're on the same line than node end
495
int commentLine = getLineNumber(commentStart, parentLineRange);
496             if (commentLine == nodeEndLine) {
497                 sameLineIdx = idx;
498             }
499             // Store previous infos
500
previousEnd = commentStart+comment.getLength();
501             endIdx = idx++;
502         }
503         if (endIdx != -1) {
504             // Verify that following node start is separated
505
if (!lastChild) {
506                 int nextLine = getLineNumber(nextStart, parentLineRange);
507                 int previousLine = getLineNumber(previousEnd, parentLineRange);
508                 if((nextLine - previousLine) <= 1) {
509                     if (sameLineIdx == -1) return nodeEnd;
510                     endIdx = sameLineIdx;
511                 }
512             }
513             // Store trailing comments indexes
514
if (++this.trailingPtr == 0) {
515                 this.trailingNodes = new ASTNode[STORAGE_INCREMENT];
516                 this.trailingIndexes = new long[STORAGE_INCREMENT];
517                 this.lastTrailingPtr = -1;
518             } else if (this.trailingPtr == this.trailingNodes.length) {
519                 int newLength = (this.trailingPtr*3/2)+STORAGE_INCREMENT;
520                 System.arraycopy(this.trailingNodes, 0, this.trailingNodes = new ASTNode[newLength], 0, this.trailingPtr);
521                 System.arraycopy(this.trailingIndexes, 0, this.trailingIndexes = new long[newLength], 0, this.trailingPtr);
522             }
523             this.trailingNodes[this.trailingPtr] = node;
524             long nodeRange = (((long)startIdx)<<32) + endIdx;
525             this.trailingIndexes[this.trailingPtr] = nodeRange;
526             // Compute new extended end
527
extended = this.comments[endIdx].getStartPosition()+this.comments[endIdx].getLength()-1;
528             // Look for children unresolved extended end
529
ASTNode previousNode = node;
530             int ptr = this.trailingPtr - 1; // children extended end were stored before
531
while (ptr >= 0) {
532                 long range = this.trailingIndexes[ptr];
533                 if (range != -1) break; // there's no more unresolved nodes
534
ASTNode unresolved = this.trailingNodes[ptr];
535                 if (previousNode != unresolved.getParent()) break; // we're no longer in node ancestor hierarchy
536
this.trailingIndexes[ptr] = nodeRange;
537                 previousNode = unresolved;
538                 ptr--; // get previous node
539
}
540             // Remove remaining unresolved nodes
541
if (ptr > this.lastTrailingPtr) {
542                 int offset = ptr - this.lastTrailingPtr;
543                 for (int i=ptr+1; i<=this.trailingPtr; i++) {
544                     this.trailingNodes[i-offset] = this.trailingNodes[i];
545                     this.trailingIndexes[i-offset] = this.trailingIndexes[i];
546                 }
547                 this.trailingPtr -= offset;
548             }
549             this.lastTrailingPtr = this.trailingPtr;
550         }
551         return extended;
552     }
553
554     class CommentMapperVisitor extends DefaultASTVisitor {
555
556         ASTNode topSiblingParent = null;
557         ASTNode[] siblings = new ASTNode[10];
558         int[][] parentLineRange = new int[10][];
559         int siblingPtr = -1;
560
561         protected boolean visitNode(ASTNode node) {
562
563             // Get default previous end
564
ASTNode parent = node.getParent();
565             int previousEnd = parent.getStartPosition();
566             
567             // Look for sibling node
568
ASTNode sibling = parent == this.topSiblingParent ? (ASTNode) this.siblings[this.siblingPtr] : null;
569             if (sibling != null) {
570                 // Found one previous sibling, so compute its trailing comments using current node start position
571
try {
572                     previousEnd = storeTrailingComments(sibling, node.getStartPosition(), false, this.parentLineRange[this.siblingPtr]);
573                 } catch (Exception JavaDoc ex) {
574                     // Give up extended ranges at this level if unexpected exception happens...
575
}
576             }
577
578             // Stop visit for malformed node (see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=84049)
579
if ((node.typeAndFlags & ASTNode.MALFORMED) != 0) {
580                 return false;
581             }
582
583             // Compute leading comments for current node
584
int[] previousLineRange = this.siblingPtr > -1 ? this.parentLineRange[this.siblingPtr] : new int[] {1, DefaultCommentMapper.this.scanner.linePtr+1};
585             try {
586                 storeLeadingComments(node, previousEnd, previousLineRange);
587             } catch (Exception JavaDoc ex) {
588                 // Give up extended ranges at this level if unexpected exception happens...
589
}
590             
591             // Store current node as waiting sibling for its parent
592
if (this.topSiblingParent != parent) {
593                 if (this.siblings.length == ++this.siblingPtr) {
594                     System.arraycopy(this.siblings, 0, this.siblings = new ASTNode[this.siblingPtr*2], 0, this.siblingPtr);
595                     System.arraycopy(this.parentLineRange, 0, this.parentLineRange = new int[this.siblingPtr*2][], 0, this.siblingPtr);
596                 }
597                 if (this.topSiblingParent == null) {
598                     // node is a CompilationUnit
599
this.parentLineRange[this.siblingPtr] = previousLineRange;
600                 } else {
601                     int parentStart = parent.getStartPosition();
602                     int firstLine = getLineNumber(parentStart, previousLineRange);
603                     int lastLine = getLineNumber(parentStart + parent.getLength() - 1, previousLineRange);
604                     if (this.parentLineRange[this.siblingPtr] == null) {
605                         this.parentLineRange[this.siblingPtr] = new int[] {firstLine, lastLine};
606                     } else {
607                         int[] lineRange = this.parentLineRange[this.siblingPtr];
608                         lineRange[0] = firstLine;
609                         lineRange[1] = lastLine;
610                     }
611                 }
612                 this.topSiblingParent = parent;
613             }
614             this.siblings[this.siblingPtr] = node;
615
616             // We're always ok to visit sub-levels
617
return true;
618         }
619         
620         protected void endVisitNode(ASTNode node) {
621
622             // Look if a child node is waiting for trailing comments computing
623
ASTNode sibling = this.topSiblingParent == node ? (ASTNode) this.siblings[this.siblingPtr] : null;
624             if (sibling != null) {
625                 try {
626                     storeTrailingComments(sibling, node.getStartPosition()+node.getLength()-1, true, this.parentLineRange[this.siblingPtr]);
627                 } catch (Exception JavaDoc ex) {
628                     // Give up extended ranges at this level if unexpected exception happens...
629
}
630             }
631             // Remove sibling if needed
632
if (this.topSiblingParent != null /*not a CompilationUnit*/
633                     && this.topSiblingParent == node) {
634                 this.siblingPtr--;
635                 this.topSiblingParent = node.getParent();
636             }
637         }
638
639         public boolean visit ( CompilationUnit node) {
640             // do nothing special, just go down in sub-levels
641
return true;
642         }
643     }
644 }
645
Popular Tags