Source Code Cross Referenced for DefaultCommentMapper.java in  » IDE-Eclipse » jdt » org » eclipse » jdt » core » dom » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » IDE Eclipse » jdt » org.eclipse.jdt.core.dom 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*******************************************************************************
002:         * Copyright (c) 2004, 2007 IBM Corporation and others.
003:         * All rights reserved. This program and the accompanying materials
004:         * are made available under the terms of the Eclipse Public License v1.0
005:         * which accompanies this distribution, and is available at
006:         * http://www.eclipse.org/legal/epl-v10.html
007:         *
008:         * Contributors:
009:         *     IBM Corporation - initial API and implementation
010:         *******************************************************************************/package org.eclipse.jdt.core.dom;
011:
012:        import org.eclipse.jdt.core.compiler.CharOperation;
013:        import org.eclipse.jdt.core.compiler.InvalidInputException;
014:        import org.eclipse.jdt.internal.compiler.parser.Scanner;
015:        import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
016:        import org.eclipse.jdt.internal.compiler.util.Util;
017:
018:        /**
019:         * Internal class for associating comments with AST nodes.
020:         * 
021:         * @since 3.0
022:         */
023:        class DefaultCommentMapper {
024:            Comment[] comments;
025:            Scanner scanner;
026:
027:            // extended nodes storage
028:            int leadingPtr;
029:            ASTNode[] leadingNodes;
030:            long[] leadingIndexes;
031:            int trailingPtr, lastTrailingPtr;
032:            ASTNode[] trailingNodes;
033:            long[] trailingIndexes;
034:            static final int STORAGE_INCREMENT = 16;
035:
036:            /**
037:             * @param table the given table of comments
038:             */
039:            DefaultCommentMapper(Comment[] table) {
040:                this .comments = table;
041:            }
042:
043:            boolean hasSameTable(Comment[] table) {
044:                return this .comments == table;
045:            }
046:
047:            /**
048:             * Get comment of the list which includes a given position
049:             * 
050:             * @param position The position belonging to the looked up comment
051:             * @return comment which includes the given position or null if none was found
052:             */
053:            Comment getComment(int position) {
054:
055:                if (this .comments == null) {
056:                    return null;
057:                }
058:                int size = this .comments.length;
059:                if (size == 0) {
060:                    return null;
061:                }
062:                int index = getCommentIndex(0, position, 0);
063:                if (index < 0) {
064:                    return null;
065:                }
066:                return this .comments[index];
067:            }
068:
069:            /*
070:             * Get the index of comment which contains given position.
071:             * If there's no matching comment, then return depends on exact parameter:
072:             *		= 0: return -1
073:             *		< 0: return index of the comment before the given position
074:             *		> 0: return index of the comment after the given position
075:             */
076:            private int getCommentIndex(int start, int position, int exact) {
077:                if (position == 0) {
078:                    if (this .comments.length > 0
079:                            && this .comments[0].getStartPosition() == 0) {
080:                        return 0;
081:                    }
082:                    return -1;
083:                }
084:                int bottom = start, top = this .comments.length - 1;
085:                int i = 0, index = -1;
086:                Comment comment = null;
087:                while (bottom <= top) {
088:                    i = bottom + (top - bottom) / 2;
089:                    comment = this .comments[i];
090:                    int commentStart = comment.getStartPosition();
091:                    if (position < commentStart) {
092:                        top = i - 1;
093:                    } else if (position >= (commentStart + comment.getLength())) {
094:                        bottom = i + 1;
095:                    } else {
096:                        index = i;
097:                        break;
098:                    }
099:                }
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)
128:                            range = this .leadingIndexes[i];
129:                    }
130:                    if (range >= 0) {
131:                        return this .comments[(int) (range >> 32)]
132:                                .getStartPosition();
133:                    }
134:                }
135:                return node.getStartPosition();
136:            }
137:
138:            /*
139:             * Search the line number corresponding to a specific position
140:             * between the given line range (inclusive)
141:             * @param position int
142:             * @parem lineRange size-2 int[]
143:             * @return int
144:             */
145:            public final int getLineNumber(int position, int[] lineRange) {
146:                int[] lineEnds = this .scanner.lineEnds;
147:                int length = lineEnds.length;
148:                return Util.getLineNumber(position, lineEnds,
149:                        (lineRange[0] > length ? length : lineRange[0]) - 1,
150:                        (lineRange[1] > length ? length : lineRange[1]) - 1);
151:            }
152:
153:            /*
154:             * Returns the extended end position of the given node.
155:             */
156:            public int getExtendedEnd(ASTNode node) {
157:                int end = node.getStartPosition() + node.getLength();
158:                if (this .trailingPtr >= 0) {
159:                    long range = -1;
160:                    for (int i = 0; range < 0 && i <= this .trailingPtr; i++) {
161:                        if (this .trailingNodes[i] == node)
162:                            range = this .trailingIndexes[i];
163:                    }
164:                    if (range >= 0) {
165:                        Comment lastComment = this .comments[(int) range];
166:                        end = lastComment.getStartPosition()
167:                                + lastComment.getLength();
168:                    }
169:                }
170:                return end - 1;
171:            }
172:
173:            /**
174:             * Returns the extended source length of the given node. Unlike
175:             * {@link ASTNode#getStartPosition()} and {@link ASTNode#getLength()},
176:             * the extended source range may include comments and whitespace
177:             * immediately before or after the normal source range for the node.
178:             * 
179:             * @param node the node
180:             * @return a (possibly 0) length, or <code>0</code>
181:             *    if no source position information is recorded for this node
182:             * @see #getExtendedStartPosition(ASTNode)
183:             * @see #getExtendedEnd(ASTNode)
184:             * @since 3.0
185:             */
186:            public int getExtendedLength(ASTNode node) {
187:                return getExtendedEnd(node) - getExtendedStartPosition(node)
188:                        + 1;
189:            }
190:
191:            /**
192:             * Return index of first leading comment of a given node.
193:             * 
194:             * @param node
195:             * @return index of first leading comment or -1 if node has no leading comment
196:             */
197:            int firstLeadingCommentIndex(ASTNode node) {
198:                if (this .leadingPtr >= 0) {
199:                    for (int i = 0; i <= this .leadingPtr; i++) {
200:                        if (this .leadingNodes[i] == node) {
201:                            return (int) (this .leadingIndexes[i] >> 32);
202:                        }
203:                    }
204:                }
205:                return -1;
206:            }
207:
208:            /**
209:             * Return index of last trailing comment of a given node.
210:             * 
211:             * @param node
212:             * @return index of last trailing comment or -1 if node has no trailing comment
213:             */
214:            int lastTrailingCommentIndex(ASTNode node) {
215:                if (this .trailingPtr >= 0) {
216:                    for (int i = 0; i <= this .trailingPtr; i++) {
217:                        if (this .trailingNodes[i] == node) {
218:                            return (int) this .trailingIndexes[i];
219:                        }
220:                    }
221:                }
222:                return -1;
223:            }
224:
225:            /*
226:             * Initialize leading and trailing comments tables in whole nodes hierarchy of a compilation
227:             * unit.
228:             * Scanner is necessary to scan between nodes and comments and verify if there's
229:             * nothing else than white spaces.
230:             */
231:            void initialize(CompilationUnit unit, Scanner sc) {
232:
233:                // Init array pointers
234:                this .leadingPtr = -1;
235:                this .trailingPtr = -1;
236:
237:                // Init comments
238:                this .comments = unit.optionalCommentTable;
239:                if (this .comments == null) {
240:                    return;
241:                }
242:                int size = this .comments.length;
243:                if (size == 0) {
244:                    return;
245:                }
246:
247:                // Init scanner and start ranges computing
248:                this .scanner = sc;
249:                this .scanner.tokenizeWhiteSpace = true;
250:
251:                // Start unit visit
252:                DefaultASTVisitor commentVisitor = new CommentMapperVisitor();
253:                unit.accept(commentVisitor);
254:
255:                // Reduce leading arrays if necessary
256:                int leadingCount = this .leadingPtr + 1;
257:                if (leadingCount > 0
258:                        && leadingCount < this .leadingIndexes.length) {
259:                    System.arraycopy(this .leadingNodes, 0,
260:                            this .leadingNodes = new ASTNode[leadingCount], 0,
261:                            leadingCount);
262:                    System.arraycopy(this .leadingIndexes, 0,
263:                            this .leadingIndexes = new long[leadingCount], 0,
264:                            leadingCount);
265:                }
266:
267:                // Reduce trailing arrays if necessary
268:                if (this .trailingPtr >= 0) {
269:                    // remove last remaining unresolved nodes
270:                    while (this .trailingIndexes[this .trailingPtr] == -1) {
271:                        this .trailingPtr--;
272:                        if (this .trailingPtr < 0) {
273:                            this .trailingIndexes = null;
274:                            this .trailingNodes = null;
275:                            break;
276:                        }
277:                    }
278:
279:                    // reduce array size
280:                    int trailingCount = this .trailingPtr + 1;
281:                    if (trailingCount > 0
282:                            && trailingCount < this .trailingIndexes.length) {
283:                        System
284:                                .arraycopy(
285:                                        this .trailingNodes,
286:                                        0,
287:                                        this .trailingNodes = new ASTNode[trailingCount],
288:                                        0, trailingCount);
289:                        System.arraycopy(this .trailingIndexes, 0,
290:                                this .trailingIndexes = new long[trailingCount],
291:                                0, trailingCount);
292:                    }
293:                }
294:
295:                // Release scanner as it's only used during unit visit
296:                this .scanner = null;
297:            }
298:
299:            /**
300:             * Search and store node leading comments. Comments are searched in position range
301:             * from previous extended position to node start position. If one or several comment are found,
302:             * returns first comment start position, otherwise returns node start position.
303:             * <p>
304:             * Starts to search for first comment before node start position and return if none was found...
305:             *</p><p>
306:             * When first comment is found before node, goes up in comment list until one of
307:             * following conditions becomes true:
308:             * <ol>
309:             * 	<li>comment end is before previous end</li>
310:             * 	<li>comment start and previous end is on the same line but not on same line of node start</li>
311:             * 	<li>there's other than white characters between current node and comment</li>
312:             * 	<li>there's more than 1 line between current node and comment</li>
313:             * </ol>
314:             * If some comment have been found, then no token should be on
315:             * on the same line before, so remove all comments which do not verify this assumption.
316:             * </p><p>
317:             * If finally there's leading still comments, then stores indexes of the first and last one
318:             * in leading comments table.
319:             */
320:            int storeLeadingComments(ASTNode node, int previousEnd,
321:                    int[] parentLineRange) {
322:                // Init extended position
323:                int nodeStart = node.getStartPosition();
324:                int extended = nodeStart;
325:
326:                // Get line of node start position
327:                int previousEndLine = getLineNumber(previousEnd,
328:                        parentLineRange);
329:                int nodeStartLine = getLineNumber(nodeStart, parentLineRange);
330:
331:                // Find first comment index
332:                int idx = getCommentIndex(0, nodeStart, -1);
333:                if (idx == -1) {
334:                    return nodeStart;
335:                }
336:
337:                // Look after potential comments
338:                int startIdx = -1;
339:                int endIdx = idx;
340:                int previousStart = nodeStart;
341:                while (idx >= 0 && previousStart >= previousEnd) {
342:                    // Verify for each comment that there's only white spaces between end and start of {following comment|node}
343:                    Comment comment = this .comments[idx];
344:                    int commentStart = comment.getStartPosition();
345:                    int end = commentStart + comment.getLength() - 1;
346:                    int commentLine = getLineNumber(commentStart,
347:                            parentLineRange);
348:                    if (end <= previousEnd
349:                            || (commentLine == previousEndLine && commentLine != nodeStartLine)) {
350:                        // stop search on condition 1) and 2)
351:                        break;
352:                    } else if ((end + 1) < previousStart) { // may be equals => then no scan is necessary
353:                        this .scanner.resetTo(end + 1, previousStart);
354:                        try {
355:                            int token = this .scanner.getNextToken();
356:                            if (token != TerminalTokens.TokenNameWHITESPACE
357:                                    || this .scanner.currentPosition != previousStart) {
358:                                // stop search on condition 3)
359:                                // if first comment fails, then there's no extended position in fact
360:                                if (idx == endIdx) {
361:                                    return nodeStart;
362:                                }
363:                                break;
364:                            }
365:                        } catch (InvalidInputException e) {
366:                            // Should not happen, but return no extended position...
367:                            return nodeStart;
368:                        }
369:                        // verify that there's no more than one line between node/comments
370:                        char[] gap = this .scanner.getCurrentIdentifierSource();
371:                        int nbrLine = 0;
372:                        int pos = -1;
373:                        while ((pos = CharOperation.indexOf('\n', gap, pos + 1)) >= 0) {
374:                            nbrLine++;
375:                        }
376:                        if (nbrLine > 1) {
377:                            // stop search on condition 4)
378:                            break;
379:                        }
380:                    }
381:                    // Store previous infos
382:                    previousStart = commentStart;
383:                    startIdx = idx--;
384:                }
385:                if (startIdx != -1) {
386:                    // Verify that there's no token on the same line before first leading comment
387:                    int commentStart = this .comments[startIdx]
388:                            .getStartPosition();
389:                    if (previousEnd < commentStart
390:                            && previousEndLine != nodeStartLine) {
391:                        int lastTokenEnd = previousEnd;
392:                        this .scanner.resetTo(previousEnd, commentStart);
393:                        try {
394:                            while (this .scanner.currentPosition < commentStart) {
395:                                if (this .scanner.getNextToken() != TerminalTokens.TokenNameWHITESPACE) {
396:                                    lastTokenEnd = this .scanner
397:                                            .getCurrentTokenEndPosition();
398:                                }
399:                            }
400:                        } catch (InvalidInputException e) {
401:                            // do nothing
402:                        }
403:                        int lastTokenLine = getLineNumber(lastTokenEnd,
404:                                parentLineRange);
405:                        int length = this .comments.length;
406:                        while (startIdx < length
407:                                && lastTokenLine == getLineNumber(
408:                                        this .comments[startIdx]
409:                                                .getStartPosition(),
410:                                        parentLineRange)
411:                                && nodeStartLine != lastTokenLine) {
412:                            startIdx++;
413:                        }
414:                    }
415:                    // Store leading comments indexes
416:                    if (startIdx <= endIdx) {
417:                        if (++this .leadingPtr == 0) {
418:                            this .leadingNodes = new ASTNode[STORAGE_INCREMENT];
419:                            this .leadingIndexes = new long[STORAGE_INCREMENT];
420:                        } else if (this .leadingPtr == this .leadingNodes.length) {
421:                            int newLength = (this .leadingPtr * 3 / 2)
422:                                    + STORAGE_INCREMENT;
423:                            System.arraycopy(this .leadingNodes, 0,
424:                                    this .leadingNodes = new ASTNode[newLength],
425:                                    0, this .leadingPtr);
426:                            System.arraycopy(this .leadingIndexes, 0,
427:                                    this .leadingIndexes = new long[newLength],
428:                                    0, this .leadingPtr);
429:                        }
430:                        this .leadingNodes[this .leadingPtr] = node;
431:                        this .leadingIndexes[this .leadingPtr] = (((long) startIdx) << 32)
432:                                + endIdx;
433:                        extended = this .comments[endIdx].getStartPosition();
434:                    }
435:                }
436:                return extended;
437:            }
438:
439:            /**
440:             * Search and store node trailing comments. Comments are searched in position range
441:             * from node end position to specified next start. If one or several comment are found,
442:             * returns last comment end position, otherwise returns node end position.
443:             * <p>
444:             * Starts to search for first comment after node end position and return if none was found...
445:             *</p><p>
446:             * When first comment is found after node, goes down in comment list until one of
447:             * following conditions becomes true:
448:             * <ol>
449:             * 	<li>comment start is after next start</li>
450:             * 	<li>there's other than white characters between current node and comment</li>
451:             * 	<li>there's more than 1 line between current node and comment</li>
452:             *</ol>
453:             * If at least potential comments have been found, then all of them has to be separated
454:             * from following node. So, remove all comments which do not verify this assumption.
455:             * Note that this verification is not applicable on last node.
456:             * </p><p>
457:             * If finally there's still trailing comments, then stores indexes of the first and last one
458:             * in trailing comments table.
459:             */
460:            int storeTrailingComments(ASTNode node, int nextStart,
461:                    boolean lastChild, int[] parentLineRange) {
462:
463:                // Init extended position
464:                int nodeEnd = node.getStartPosition() + node.getLength() - 1;
465:                if (nodeEnd == nextStart) {
466:                    // special case for last child of its parent
467:                    if (++this .trailingPtr == 0) {
468:                        this .trailingNodes = new ASTNode[STORAGE_INCREMENT];
469:                        this .trailingIndexes = new long[STORAGE_INCREMENT];
470:                        this .lastTrailingPtr = -1;
471:                    } else if (this .trailingPtr == this .trailingNodes.length) {
472:                        int newLength = (this .trailingPtr * 3 / 2)
473:                                + STORAGE_INCREMENT;
474:                        System.arraycopy(this .trailingNodes, 0,
475:                                this .trailingNodes = new ASTNode[newLength], 0,
476:                                this .trailingPtr);
477:                        System.arraycopy(this .trailingIndexes, 0,
478:                                this .trailingIndexes = new long[newLength], 0,
479:                                this .trailingPtr);
480:                    }
481:                    this .trailingNodes[this .trailingPtr] = node;
482:                    this .trailingIndexes[this .trailingPtr] = -1;
483:                    return nodeEnd;
484:                }
485:                int extended = nodeEnd;
486:
487:                // Get line number
488:                int nodeEndLine = getLineNumber(nodeEnd, parentLineRange);
489:
490:                // Find comments range index
491:                int idx = getCommentIndex(0, nodeEnd, 1);
492:                if (idx == -1) {
493:                    return nodeEnd;
494:                }
495:
496:                // Look after potential comments
497:                int startIdx = idx;
498:                int endIdx = -1;
499:                int length = this .comments.length;
500:                int commentStart = extended + 1;
501:                int previousEnd = nodeEnd + 1;
502:                int sameLineIdx = -1;
503:                while (idx < length && commentStart < nextStart) {
504:                    // get comment and leave if next starting position has been reached
505:                    Comment comment = this .comments[idx];
506:                    commentStart = comment.getStartPosition();
507:                    // verify that there's nothing else than white spaces between node/comments
508:                    if (commentStart >= nextStart) {
509:                        // stop search on condition 1)
510:                        break;
511:                    } else if (previousEnd < commentStart) {
512:                        this .scanner.resetTo(previousEnd, commentStart);
513:                        try {
514:                            int token = this .scanner.getNextToken();
515:                            if (token != TerminalTokens.TokenNameWHITESPACE
516:                                    || this .scanner.currentPosition != commentStart) {
517:                                // stop search on condition 2)
518:                                // if first index fails, then there's no extended position in fact...
519:                                if (idx == startIdx) {
520:                                    return nodeEnd;
521:                                }
522:                                // otherwise we get the last index of trailing comment => break
523:                                break;
524:                            }
525:                        } catch (InvalidInputException e) {
526:                            // Should not happen, but return no extended position...
527:                            return nodeEnd;
528:                        }
529:                        // verify that there's no more than one line between node/comments
530:                        char[] gap = this .scanner.getCurrentIdentifierSource();
531:                        int nbrLine = 0;
532:                        int pos = -1;
533:                        while ((pos = CharOperation.indexOf('\n', gap, pos + 1)) >= 0) {
534:                            nbrLine++;
535:                        }
536:                        if (nbrLine > 1) {
537:                            // stop search on condition 3)
538:                            break;
539:                        }
540:                    }
541:                    // Store index if we're on the same line than node end
542:                    int commentLine = getLineNumber(commentStart,
543:                            parentLineRange);
544:                    if (commentLine == nodeEndLine) {
545:                        sameLineIdx = idx;
546:                    }
547:                    // Store previous infos
548:                    previousEnd = commentStart + comment.getLength();
549:                    endIdx = idx++;
550:                }
551:                if (endIdx != -1) {
552:                    // Verify that following node start is separated
553:                    if (!lastChild) {
554:                        int nextLine = getLineNumber(nextStart, parentLineRange);
555:                        int previousLine = getLineNumber(previousEnd,
556:                                parentLineRange);
557:                        if ((nextLine - previousLine) <= 1) {
558:                            if (sameLineIdx == -1)
559:                                return nodeEnd;
560:                            endIdx = sameLineIdx;
561:                        }
562:                    }
563:                    // Store trailing comments indexes
564:                    if (++this .trailingPtr == 0) {
565:                        this .trailingNodes = new ASTNode[STORAGE_INCREMENT];
566:                        this .trailingIndexes = new long[STORAGE_INCREMENT];
567:                        this .lastTrailingPtr = -1;
568:                    } else if (this .trailingPtr == this .trailingNodes.length) {
569:                        int newLength = (this .trailingPtr * 3 / 2)
570:                                + STORAGE_INCREMENT;
571:                        System.arraycopy(this .trailingNodes, 0,
572:                                this .trailingNodes = new ASTNode[newLength], 0,
573:                                this .trailingPtr);
574:                        System.arraycopy(this .trailingIndexes, 0,
575:                                this .trailingIndexes = new long[newLength], 0,
576:                                this .trailingPtr);
577:                    }
578:                    this .trailingNodes[this .trailingPtr] = node;
579:                    long nodeRange = (((long) startIdx) << 32) + endIdx;
580:                    this .trailingIndexes[this .trailingPtr] = nodeRange;
581:                    // Compute new extended end
582:                    extended = this .comments[endIdx].getStartPosition()
583:                            + this .comments[endIdx].getLength() - 1;
584:                    // Look for children unresolved extended end
585:                    ASTNode previousNode = node;
586:                    int ptr = this .trailingPtr - 1; // children extended end were stored before
587:                    while (ptr >= 0) {
588:                        long range = this .trailingIndexes[ptr];
589:                        if (range != -1)
590:                            break; // there's no more unresolved nodes
591:                        ASTNode unresolved = this .trailingNodes[ptr];
592:                        if (previousNode != unresolved.getParent())
593:                            break; // we're no longer in node ancestor hierarchy
594:                        this .trailingIndexes[ptr] = nodeRange;
595:                        previousNode = unresolved;
596:                        ptr--; // get previous node
597:                    }
598:                    // Remove remaining unresolved nodes
599:                    if (ptr > this .lastTrailingPtr) {
600:                        int offset = ptr - this .lastTrailingPtr;
601:                        for (int i = ptr + 1; i <= this .trailingPtr; i++) {
602:                            this .trailingNodes[i - offset] = this .trailingNodes[i];
603:                            this .trailingIndexes[i - offset] = this .trailingIndexes[i];
604:                        }
605:                        this .trailingPtr -= offset;
606:                    }
607:                    this .lastTrailingPtr = this .trailingPtr;
608:                }
609:                return extended;
610:            }
611:
612:            class CommentMapperVisitor extends DefaultASTVisitor {
613:
614:                ASTNode topSiblingParent = null;
615:                ASTNode[] siblings = new ASTNode[10];
616:                int[][] parentLineRange = new int[10][];
617:                int siblingPtr = -1;
618:
619:                protected boolean visitNode(ASTNode node) {
620:
621:                    // Get default previous end
622:                    ASTNode parent = node.getParent();
623:                    int previousEnd = parent.getStartPosition();
624:
625:                    // Look for sibling node
626:                    ASTNode sibling = parent == this .topSiblingParent ? (ASTNode) this .siblings[this .siblingPtr]
627:                            : null;
628:                    if (sibling != null) {
629:                        // Found one previous sibling, so compute its trailing comments using current node start position
630:                        try {
631:                            previousEnd = storeTrailingComments(sibling, node
632:                                    .getStartPosition(), false,
633:                                    this .parentLineRange[this .siblingPtr]);
634:                        } catch (Exception ex) {
635:                            // Give up extended ranges at this level if unexpected exception happens...
636:                        }
637:                    }
638:
639:                    // Stop visit for malformed node (see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=84049)
640:                    if ((node.typeAndFlags & ASTNode.MALFORMED) != 0) {
641:                        return false;
642:                    }
643:
644:                    // Compute leading comments for current node
645:                    int[] previousLineRange = this .siblingPtr > -1 ? this .parentLineRange[this .siblingPtr]
646:                            : new int[] {
647:                                    1,
648:                                    DefaultCommentMapper.this .scanner.linePtr + 1 };
649:                    try {
650:                        storeLeadingComments(node, previousEnd,
651:                                previousLineRange);
652:                    } catch (Exception ex) {
653:                        // Give up extended ranges at this level if unexpected exception happens...
654:                    }
655:
656:                    // Store current node as waiting sibling for its parent
657:                    if (this .topSiblingParent != parent) {
658:                        if (this .siblings.length == ++this .siblingPtr) {
659:                            System
660:                                    .arraycopy(
661:                                            this .siblings,
662:                                            0,
663:                                            this .siblings = new ASTNode[this .siblingPtr * 2],
664:                                            0, this .siblingPtr);
665:                            System
666:                                    .arraycopy(
667:                                            this .parentLineRange,
668:                                            0,
669:                                            this .parentLineRange = new int[this .siblingPtr * 2][],
670:                                            0, this .siblingPtr);
671:                        }
672:                        if (this .topSiblingParent == null) {
673:                            // node is a CompilationUnit
674:                            this .parentLineRange[this .siblingPtr] = previousLineRange;
675:                        } else {
676:                            int parentStart = parent.getStartPosition();
677:                            int firstLine = getLineNumber(parentStart,
678:                                    previousLineRange);
679:                            int lastLine = getLineNumber(parentStart
680:                                    + parent.getLength() - 1, previousLineRange);
681:                            if (this .parentLineRange[this .siblingPtr] == null) {
682:                                this .parentLineRange[this .siblingPtr] = new int[] {
683:                                        firstLine, lastLine };
684:                            } else {
685:                                int[] lineRange = this .parentLineRange[this .siblingPtr];
686:                                lineRange[0] = firstLine;
687:                                lineRange[1] = lastLine;
688:                            }
689:                        }
690:                        this .topSiblingParent = parent;
691:                    }
692:                    this .siblings[this .siblingPtr] = node;
693:
694:                    // We're always ok to visit sub-levels
695:                    return true;
696:                }
697:
698:                protected void endVisitNode(ASTNode node) {
699:
700:                    // Look if a child node is waiting for trailing comments computing
701:                    ASTNode sibling = this .topSiblingParent == node ? (ASTNode) this .siblings[this .siblingPtr]
702:                            : null;
703:                    if (sibling != null) {
704:                        try {
705:                            storeTrailingComments(sibling, node
706:                                    .getStartPosition()
707:                                    + node.getLength() - 1, true,
708:                                    this .parentLineRange[this .siblingPtr]);
709:                        } catch (Exception ex) {
710:                            // Give up extended ranges at this level if unexpected exception happens...
711:                        }
712:                    }
713:                    // Remove sibling if needed
714:                    if (this .topSiblingParent != null /*not a CompilationUnit*/
715:                            && this .topSiblingParent == node) {
716:                        this .siblingPtr--;
717:                        this .topSiblingParent = node.getParent();
718:                    }
719:                }
720:
721:                public boolean visit(CompilationUnit node) {
722:                    // do nothing special, just go down in sub-levels
723:                    return true;
724:                }
725:            }
726:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.