Source Code Cross Referenced for Scribe.java in  » IDE-Eclipse » jdt » org » eclipse » jdt » internal » formatter » 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.internal.formatter 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*******************************************************************************
0002:         * Copyright (c) 2000, 2007 IBM Corporation and others.
0003:         * All rights reserved. This program and the accompanying materials
0004:         * are made available under the terms of the Eclipse Public License v1.0
0005:         * which accompanies this distribution, and is available at
0006:         * http://www.eclipse.org/legal/epl-v10.html
0007:         *
0008:         * Contributors:
0009:         *     IBM Corporation - initial API and implementation
0010:         *******************************************************************************/package org.eclipse.jdt.internal.formatter;
0011:
0012:        import java.util.Arrays;
0013:
0014:        import org.eclipse.jdt.core.compiler.CharOperation;
0015:        import org.eclipse.jdt.core.compiler.InvalidInputException;
0016:        import org.eclipse.jdt.internal.compiler.ASTVisitor;
0017:        import org.eclipse.jdt.internal.compiler.ast.Annotation;
0018:        import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
0019:        import org.eclipse.jdt.internal.compiler.parser.Scanner;
0020:        import org.eclipse.jdt.internal.compiler.parser.ScannerHelper;
0021:        import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
0022:        import org.eclipse.jdt.internal.compiler.util.Util;
0023:        import org.eclipse.jdt.internal.core.util.CodeSnippetParsingUtil;
0024:        import org.eclipse.jdt.internal.core.util.RecordedParsingInformation;
0025:        import org.eclipse.jdt.internal.formatter.align.Alignment;
0026:        import org.eclipse.jdt.internal.formatter.align.AlignmentException;
0027:        import org.eclipse.text.edits.MultiTextEdit;
0028:        import org.eclipse.text.edits.ReplaceEdit;
0029:        import org.eclipse.text.edits.TextEdit;
0030:
0031:        /**
0032:         * This class is responsible for dumping formatted source
0033:         * @since 2.1
0034:         */
0035:        public class Scribe {
0036:            private static final int INITIAL_SIZE = 100;
0037:
0038:            private boolean checkLineWrapping;
0039:            /** one-based column */
0040:            public int column;
0041:            private int[][] commentPositions;
0042:
0043:            // Most specific alignment. 
0044:            public Alignment currentAlignment;
0045:            public int currentToken;
0046:
0047:            // edits management
0048:            private OptimizedReplaceEdit[] edits;
0049:            public int editsIndex;
0050:
0051:            public CodeFormatterVisitor formatter;
0052:            public int indentationLevel;
0053:            public int lastNumberOfNewLines;
0054:            public int line;
0055:
0056:            private int[] lineEnds;
0057:            private String lineSeparator;
0058:            public Alignment memberAlignment;
0059:            public boolean needSpace = false;
0060:
0061:            public int nlsTagCounter;
0062:            public int pageWidth;
0063:            public boolean pendingSpace = false;
0064:
0065:            public Scanner scanner;
0066:            public int scannerEndPosition;
0067:            public int tabLength;
0068:            public int indentationSize;
0069:            private int textRegionEnd;
0070:            private int textRegionStart;
0071:            public int tabChar;
0072:            public int numberOfIndentations;
0073:            private boolean useTabsOnlyForLeadingIndents;
0074:
0075:            /** indent empty lines*/
0076:            private final boolean indentEmptyLines;
0077:
0078:            private final boolean formatJavadocComment;
0079:            private final boolean formatBlockComment;
0080:
0081:            Scribe(CodeFormatterVisitor formatter, long sourceLevel,
0082:                    int offset, int length,
0083:                    CodeSnippetParsingUtil codeSnippetParsingUtil) {
0084:                this .scanner = new Scanner(true, true, false/*nls*/,
0085:                        sourceLevel/*sourceLevel*/, null/*taskTags*/,
0086:                        null/*taskPriorities*/, true/*taskCaseSensitive*/);
0087:                this .formatter = formatter;
0088:                this .pageWidth = formatter.preferences.page_width;
0089:                this .tabLength = formatter.preferences.tab_size;
0090:                this .indentationLevel = 0; // initialize properly
0091:                this .numberOfIndentations = 0;
0092:                this .useTabsOnlyForLeadingIndents = formatter.preferences.use_tabs_only_for_leading_indentations;
0093:                this .indentEmptyLines = formatter.preferences.indent_empty_lines;
0094:                this .tabChar = formatter.preferences.tab_char;
0095:                if (this .tabChar == DefaultCodeFormatterOptions.MIXED) {
0096:                    this .indentationSize = formatter.preferences.indentation_size;
0097:                } else {
0098:                    this .indentationSize = this .tabLength;
0099:                }
0100:                this .lineSeparator = formatter.preferences.line_separator;
0101:                this .indentationLevel = formatter.preferences.initial_indentation_level
0102:                        * this .indentationSize;
0103:                this .textRegionStart = offset;
0104:                this .textRegionEnd = offset + length - 1;
0105:                if (codeSnippetParsingUtil != null) {
0106:                    final RecordedParsingInformation information = codeSnippetParsingUtil.recordedParsingInformation;
0107:                    if (information != null) {
0108:                        this .lineEnds = information.lineEnds;
0109:                        this .commentPositions = information.commentPositions;
0110:                    }
0111:                }
0112:                this .formatBlockComment = formatter.preferences.comment_format_block_comment;
0113:                this .formatJavadocComment = formatter.preferences.comment_format_javadoc_comment;
0114:                reset();
0115:            }
0116:
0117:            private final void addDeleteEdit(int start, int end) {
0118:                if (this .edits.length == this .editsIndex) {
0119:                    // resize
0120:                    resize();
0121:                }
0122:                addOptimizedReplaceEdit(start, end - start + 1,
0123:                        Util.EMPTY_STRING);
0124:            }
0125:
0126:            public final void addInsertEdit(int insertPosition,
0127:                    String insertedString) {
0128:                if (this .edits.length == this .editsIndex) {
0129:                    // resize
0130:                    resize();
0131:                }
0132:                addOptimizedReplaceEdit(insertPosition, 0, insertedString);
0133:            }
0134:
0135:            private final void addOptimizedReplaceEdit(int offset, int length,
0136:                    String replacement) {
0137:                if (this .editsIndex > 0) {
0138:                    // try to merge last two edits
0139:                    final OptimizedReplaceEdit previous = this .edits[this .editsIndex - 1];
0140:                    final int previousOffset = previous.offset;
0141:                    final int previousLength = previous.length;
0142:                    final int endOffsetOfPreviousEdit = previousOffset
0143:                            + previousLength;
0144:                    final int replacementLength = replacement.length();
0145:                    final String previousReplacement = previous.replacement;
0146:                    final int previousReplacementLength = previousReplacement
0147:                            .length();
0148:                    if (previousOffset == offset
0149:                            && previousLength == length
0150:                            && (replacementLength == 0 || previousReplacementLength == 0)) {
0151:                        if (this .currentAlignment != null) {
0152:                            final Location location = this .currentAlignment.location;
0153:                            if (location.editsIndex == this .editsIndex) {
0154:                                location.editsIndex--;
0155:                                location.textEdit = previous;
0156:                            }
0157:                        }
0158:                        this .editsIndex--;
0159:                        return;
0160:                    }
0161:                    if (endOffsetOfPreviousEdit == offset) {
0162:                        if (length != 0) {
0163:                            if (replacementLength != 0) {
0164:                                this .edits[this .editsIndex - 1] = new OptimizedReplaceEdit(
0165:                                        previousOffset,
0166:                                        previousLength + length,
0167:                                        previousReplacement + replacement);
0168:                            } else if (previousLength + length == previousReplacementLength) {
0169:                                // check the characters. If they are identical, we can get rid of the previous edit
0170:                                boolean canBeRemoved = true;
0171:                                loop: for (int i = previousOffset; i < previousOffset
0172:                                        + previousReplacementLength; i++) {
0173:                                    if (scanner.source[i] != previousReplacement
0174:                                            .charAt(i - previousOffset)) {
0175:                                        this .edits[this .editsIndex - 1] = new OptimizedReplaceEdit(
0176:                                                previousOffset,
0177:                                                previousReplacementLength,
0178:                                                previousReplacement);
0179:                                        canBeRemoved = false;
0180:                                        break loop;
0181:                                    }
0182:                                }
0183:                                if (canBeRemoved) {
0184:                                    if (this .currentAlignment != null) {
0185:                                        final Location location = this .currentAlignment.location;
0186:                                        if (location.editsIndex == this .editsIndex) {
0187:                                            location.editsIndex--;
0188:                                            location.textEdit = previous;
0189:                                        }
0190:                                    }
0191:                                    this .editsIndex--;
0192:                                }
0193:                            } else {
0194:                                this .edits[this .editsIndex - 1] = new OptimizedReplaceEdit(
0195:                                        previousOffset,
0196:                                        previousLength + length,
0197:                                        previousReplacement);
0198:                            }
0199:                        } else {
0200:                            if (replacementLength != 0) {
0201:                                this .edits[this .editsIndex - 1] = new OptimizedReplaceEdit(
0202:                                        previousOffset, previousLength,
0203:                                        previousReplacement + replacement);
0204:                            }
0205:                        }
0206:                    } else if ((offset + length == previousOffset)
0207:                            && (previousLength + length == replacementLength
0208:                                    + previousReplacementLength)) {
0209:                        // check if both edits corresponds to the orignal source code
0210:                        boolean canBeRemoved = true;
0211:                        String totalReplacement = replacement
0212:                                + previousReplacement;
0213:                        loop: for (int i = 0; i < previousLength + length; i++) {
0214:                            if (scanner.source[i + offset] != totalReplacement
0215:                                    .charAt(i)) {
0216:                                this .edits[this .editsIndex - 1] = new OptimizedReplaceEdit(
0217:                                        offset, previousLength + length,
0218:                                        totalReplacement);
0219:                                canBeRemoved = false;
0220:                                break loop;
0221:                            }
0222:                        }
0223:                        if (canBeRemoved) {
0224:                            if (this .currentAlignment != null) {
0225:                                final Location location = this .currentAlignment.location;
0226:                                if (location.editsIndex == this .editsIndex) {
0227:                                    location.editsIndex--;
0228:                                    location.textEdit = previous;
0229:                                }
0230:                            }
0231:                            this .editsIndex--;
0232:                        }
0233:                    } else {
0234:                        this .edits[this .editsIndex++] = new OptimizedReplaceEdit(
0235:                                offset, length, replacement);
0236:                    }
0237:                } else {
0238:                    this .edits[this .editsIndex++] = new OptimizedReplaceEdit(
0239:                            offset, length, replacement);
0240:                }
0241:            }
0242:
0243:            public final void addReplaceEdit(int start, int end,
0244:                    String replacement) {
0245:                if (this .edits.length == this .editsIndex) {
0246:                    // resize
0247:                    resize();
0248:                }
0249:                addOptimizedReplaceEdit(start, end - start + 1, replacement);
0250:            }
0251:
0252:            public void alignFragment(Alignment alignment, int fragmentIndex) {
0253:                alignment.fragmentIndex = fragmentIndex;
0254:                alignment.checkColumn();
0255:                alignment.performFragmentEffect();
0256:            }
0257:
0258:            public void checkNLSTag(int sourceStart) {
0259:                if (hasNLSTag(sourceStart)) {
0260:                    this .nlsTagCounter++;
0261:                }
0262:            }
0263:
0264:            public void consumeNextToken() {
0265:                printComment();
0266:                try {
0267:                    this .currentToken = this .scanner.getNextToken();
0268:                    addDeleteEdit(this .scanner.getCurrentTokenStartPosition(),
0269:                            this .scanner.getCurrentTokenEndPosition());
0270:                } catch (InvalidInputException e) {
0271:                    throw new AbortFormatting(e);
0272:                }
0273:            }
0274:
0275:            public Alignment createAlignment(String name, int mode, int count,
0276:                    int sourceRestart) {
0277:                return createAlignment(name, mode, Alignment.R_INNERMOST,
0278:                        count, sourceRestart);
0279:            }
0280:
0281:            public Alignment createAlignment(String name, int mode, int count,
0282:                    int sourceRestart, boolean adjust) {
0283:                return createAlignment(name, mode, Alignment.R_INNERMOST,
0284:                        count, sourceRestart, adjust);
0285:            }
0286:
0287:            public Alignment createAlignment(String name, int mode,
0288:                    int tieBreakRule, int count, int sourceRestart) {
0289:                return createAlignment(name, mode, tieBreakRule, count,
0290:                        sourceRestart,
0291:                        this .formatter.preferences.continuation_indentation,
0292:                        false);
0293:            }
0294:
0295:            public Alignment createAlignment(String name, int mode, int count,
0296:                    int sourceRestart, int continuationIndent, boolean adjust) {
0297:                return createAlignment(name, mode, Alignment.R_INNERMOST,
0298:                        count, sourceRestart, continuationIndent, adjust);
0299:            }
0300:
0301:            public Alignment createAlignment(String name, int mode,
0302:                    int tieBreakRule, int count, int sourceRestart,
0303:                    int continuationIndent, boolean adjust) {
0304:                Alignment alignment = new Alignment(name, mode, tieBreakRule,
0305:                        this , count, sourceRestart, continuationIndent);
0306:                // adjust break indentation
0307:                if (adjust && this .memberAlignment != null) {
0308:                    Alignment current = this .memberAlignment;
0309:                    while (current.enclosing != null) {
0310:                        current = current.enclosing;
0311:                    }
0312:                    if ((current.mode & Alignment.M_MULTICOLUMN) != 0) {
0313:                        final int indentSize = this .indentationSize;
0314:                        switch (current.chunkKind) {
0315:                        case Alignment.CHUNK_METHOD:
0316:                        case Alignment.CHUNK_TYPE:
0317:                            if ((mode & Alignment.M_INDENT_BY_ONE) != 0) {
0318:                                alignment.breakIndentationLevel = this .indentationLevel
0319:                                        + indentSize;
0320:                            } else {
0321:                                alignment.breakIndentationLevel = this .indentationLevel
0322:                                        + continuationIndent * indentSize;
0323:                            }
0324:                            alignment.update();
0325:                            break;
0326:                        case Alignment.CHUNK_FIELD:
0327:                            if ((mode & Alignment.M_INDENT_BY_ONE) != 0) {
0328:                                alignment.breakIndentationLevel = current.originalIndentationLevel
0329:                                        + indentSize;
0330:                            } else {
0331:                                alignment.breakIndentationLevel = current.originalIndentationLevel
0332:                                        + continuationIndent * indentSize;
0333:                            }
0334:                            alignment.update();
0335:                            break;
0336:                        }
0337:                    } else {
0338:                        switch (current.mode & Alignment.SPLIT_MASK) {
0339:                        case Alignment.M_COMPACT_SPLIT:
0340:                        case Alignment.M_COMPACT_FIRST_BREAK_SPLIT:
0341:                        case Alignment.M_NEXT_PER_LINE_SPLIT:
0342:                        case Alignment.M_NEXT_SHIFTED_SPLIT:
0343:                        case Alignment.M_ONE_PER_LINE_SPLIT:
0344:                            final int indentSize = this .indentationSize;
0345:                            switch (current.chunkKind) {
0346:                            case Alignment.CHUNK_METHOD:
0347:                            case Alignment.CHUNK_TYPE:
0348:                                if ((mode & Alignment.M_INDENT_BY_ONE) != 0) {
0349:                                    alignment.breakIndentationLevel = this .indentationLevel
0350:                                            + indentSize;
0351:                                } else {
0352:                                    alignment.breakIndentationLevel = this .indentationLevel
0353:                                            + continuationIndent * indentSize;
0354:                                }
0355:                                alignment.update();
0356:                                break;
0357:                            case Alignment.CHUNK_FIELD:
0358:                                if ((mode & Alignment.M_INDENT_BY_ONE) != 0) {
0359:                                    alignment.breakIndentationLevel = current.originalIndentationLevel
0360:                                            + indentSize;
0361:                                } else {
0362:                                    alignment.breakIndentationLevel = current.originalIndentationLevel
0363:                                            + continuationIndent * indentSize;
0364:                                }
0365:                                alignment.update();
0366:                                break;
0367:                            }
0368:                            break;
0369:                        }
0370:                    }
0371:                }
0372:                return alignment;
0373:            }
0374:
0375:            public Alignment createMemberAlignment(String name, int mode,
0376:                    int count, int sourceRestart) {
0377:                Alignment mAlignment = createAlignment(name, mode,
0378:                        Alignment.R_INNERMOST, count, sourceRestart);
0379:                mAlignment.breakIndentationLevel = this .indentationLevel;
0380:                return mAlignment;
0381:            }
0382:
0383:            public void enterAlignment(Alignment alignment) {
0384:                alignment.enclosing = this .currentAlignment;
0385:                alignment.location.lastLocalDeclarationSourceStart = this .formatter.lastLocalDeclarationSourceStart;
0386:                this .currentAlignment = alignment;
0387:            }
0388:
0389:            public void enterMemberAlignment(Alignment alignment) {
0390:                alignment.enclosing = this .memberAlignment;
0391:                alignment.location.lastLocalDeclarationSourceStart = this .formatter.lastLocalDeclarationSourceStart;
0392:                this .memberAlignment = alignment;
0393:            }
0394:
0395:            public void exitAlignment(Alignment alignment,
0396:                    boolean discardAlignment) {
0397:                Alignment current = this .currentAlignment;
0398:                while (current != null) {
0399:                    if (current == alignment)
0400:                        break;
0401:                    current = current.enclosing;
0402:                }
0403:                if (current == null) {
0404:                    throw new AbortFormatting(
0405:                            "could not find matching alignment: " + alignment); //$NON-NLS-1$
0406:                }
0407:                this .indentationLevel = alignment.location.outputIndentationLevel;
0408:                this .numberOfIndentations = alignment.location.numberOfIndentations;
0409:                this .formatter.lastLocalDeclarationSourceStart = alignment.location.lastLocalDeclarationSourceStart;
0410:                if (discardAlignment) {
0411:                    this .currentAlignment = alignment.enclosing;
0412:                }
0413:            }
0414:
0415:            public void exitMemberAlignment(Alignment alignment) {
0416:                Alignment current = this .memberAlignment;
0417:                while (current != null) {
0418:                    if (current == alignment)
0419:                        break;
0420:                    current = current.enclosing;
0421:                }
0422:                if (current == null) {
0423:                    throw new AbortFormatting(
0424:                            "could not find matching alignment: " + alignment); //$NON-NLS-1$
0425:                }
0426:                this .indentationLevel = current.location.outputIndentationLevel;
0427:                this .numberOfIndentations = current.location.numberOfIndentations;
0428:                this .formatter.lastLocalDeclarationSourceStart = alignment.location.lastLocalDeclarationSourceStart;
0429:                this .memberAlignment = current.enclosing;
0430:            }
0431:
0432:            public Alignment getAlignment(String name) {
0433:                if (this .currentAlignment != null) {
0434:                    return this .currentAlignment.getAlignment(name);
0435:                }
0436:                return null;
0437:            }
0438:
0439:            /** 
0440:             * Answer actual indentation level based on true column position
0441:             * @return int
0442:             */
0443:            public int getColumnIndentationLevel() {
0444:                return this .column - 1;
0445:            }
0446:
0447:            public final int getCommentIndex(int position) {
0448:                if (this .commentPositions == null)
0449:                    return -1;
0450:                int length = this .commentPositions.length;
0451:                if (length == 0) {
0452:                    return -1;
0453:                }
0454:                int g = 0, d = length - 1;
0455:                int m = 0;
0456:                while (g <= d) {
0457:                    m = g + (d - g) / 2;
0458:                    int bound = this .commentPositions[m][1];
0459:                    if (bound < 0) {
0460:                        bound = -bound;
0461:                    }
0462:                    if (bound < position) {
0463:                        g = m + 1;
0464:                    } else if (bound > position) {
0465:                        d = m - 1;
0466:                    } else {
0467:                        return m;
0468:                    }
0469:                }
0470:                return -(g + 1);
0471:            }
0472:
0473:            private int getCurrentCommentOffset(int start) {
0474:                int linePtr = -Arrays.binarySearch(this .lineEnds, start);
0475:                int offset = 0;
0476:                int beginningOfLine = this .getLineEnd(linePtr - 1);
0477:                if (beginningOfLine == -1) {
0478:                    beginningOfLine = 0;
0479:                }
0480:                int currentStartPosition = start;
0481:                char[] source = scanner.source;
0482:
0483:                // find the position of the beginning of the line containing the comment
0484:                while (beginningOfLine > currentStartPosition) {
0485:                    if (linePtr > 0) {
0486:                        beginningOfLine = this .getLineEnd(--linePtr);
0487:                    } else {
0488:                        beginningOfLine = 0;
0489:                        break;
0490:                    }
0491:                }
0492:                for (int i = currentStartPosition - 1; i >= beginningOfLine; i--) {
0493:                    char currentCharacter = source[i];
0494:                    switch (currentCharacter) {
0495:                    case '\t':
0496:                        offset += this .tabLength;
0497:                        break;
0498:                    case ' ':
0499:                        offset++;
0500:                        break;
0501:                    case '\r':
0502:                    case '\n':
0503:                        break;
0504:                    default:
0505:                        return offset;
0506:                    }
0507:                }
0508:                return offset;
0509:            }
0510:
0511:            public String getEmptyLines(int linesNumber) {
0512:                if (this .nlsTagCounter > 0) {
0513:                    return Util.EMPTY_STRING;
0514:                }
0515:                StringBuffer buffer = new StringBuffer();
0516:                if (lastNumberOfNewLines == 0) {
0517:                    linesNumber++; // add an extra line breaks
0518:                    for (int i = 0; i < linesNumber; i++) {
0519:                        if (indentEmptyLines)
0520:                            printIndentationIfNecessary(buffer);
0521:                        buffer.append(this .lineSeparator);
0522:                    }
0523:                    lastNumberOfNewLines += linesNumber;
0524:                    line += linesNumber;
0525:                    column = 1;
0526:                    needSpace = false;
0527:                    this .pendingSpace = false;
0528:                } else if (lastNumberOfNewLines == 1) {
0529:                    for (int i = 0; i < linesNumber; i++) {
0530:                        if (indentEmptyLines)
0531:                            printIndentationIfNecessary(buffer);
0532:                        buffer.append(this .lineSeparator);
0533:                    }
0534:                    lastNumberOfNewLines += linesNumber;
0535:                    line += linesNumber;
0536:                    column = 1;
0537:                    needSpace = false;
0538:                    this .pendingSpace = false;
0539:                } else {
0540:                    if ((lastNumberOfNewLines - 1) >= linesNumber) {
0541:                        // there is no need to add new lines
0542:                        return Util.EMPTY_STRING;
0543:                    }
0544:                    final int realNewLineNumber = linesNumber
0545:                            - lastNumberOfNewLines + 1;
0546:                    for (int i = 0; i < realNewLineNumber; i++) {
0547:                        if (indentEmptyLines)
0548:                            printIndentationIfNecessary(buffer);
0549:                        buffer.append(this .lineSeparator);
0550:                    }
0551:                    lastNumberOfNewLines += realNewLineNumber;
0552:                    line += realNewLineNumber;
0553:                    column = 1;
0554:                    needSpace = false;
0555:                    this .pendingSpace = false;
0556:                }
0557:                return String.valueOf(buffer);
0558:            }
0559:
0560:            public OptimizedReplaceEdit getLastEdit() {
0561:                if (this .editsIndex > 0) {
0562:                    return this .edits[this .editsIndex - 1];
0563:                }
0564:                return null;
0565:            }
0566:
0567:            public final int getLineEnd(int lineNumber) {
0568:                if (this .lineEnds == null)
0569:                    return -1;
0570:                if (lineNumber >= this .lineEnds.length + 1)
0571:                    return this .scannerEndPosition;
0572:                if (lineNumber <= 0)
0573:                    return -1;
0574:                return this .lineEnds[lineNumber - 1]; // next line start one character behind the lineEnd of the previous line	
0575:            }
0576:
0577:            Alignment getMemberAlignment() {
0578:                return this .memberAlignment;
0579:            }
0580:
0581:            public String getNewLine() {
0582:                if (this .nlsTagCounter > 0) {
0583:                    return Util.EMPTY_STRING;
0584:                }
0585:                if (lastNumberOfNewLines >= 1) {
0586:                    column = 1; // ensure that the scribe is at the beginning of a new line
0587:                    return Util.EMPTY_STRING;
0588:                }
0589:                line++;
0590:                lastNumberOfNewLines = 1;
0591:                column = 1;
0592:                needSpace = false;
0593:                this .pendingSpace = false;
0594:                return this .lineSeparator;
0595:            }
0596:
0597:            /** 
0598:             * Answer next indentation level based on column estimated position
0599:             * (if column is not indented, then use indentationLevel)
0600:             */
0601:            public int getNextIndentationLevel(int someColumn) {
0602:                int indent = someColumn - 1;
0603:                if (indent == 0)
0604:                    return this .indentationLevel;
0605:                if (this .tabChar == DefaultCodeFormatterOptions.TAB) {
0606:                    if (this .useTabsOnlyForLeadingIndents) {
0607:                        return indent;
0608:                    }
0609:                    int rem = indent % this .indentationSize;
0610:                    int addition = rem == 0 ? 0 : this .indentationSize - rem; // round to superior
0611:                    return indent + addition;
0612:                } else {
0613:                    return indent;
0614:                }
0615:            }
0616:
0617:            private String getPreserveEmptyLines(int count) {
0618:                if (count > 0) {
0619:                    if (this .formatter.preferences.number_of_empty_lines_to_preserve != 0) {
0620:                        int linesToPreserve = Math
0621:                                .min(
0622:                                        count,
0623:                                        this .formatter.preferences.number_of_empty_lines_to_preserve);
0624:                        return this .getEmptyLines(linesToPreserve);
0625:                    } else {
0626:                        return getNewLine();
0627:                    }
0628:                }
0629:                return Util.EMPTY_STRING;
0630:            }
0631:
0632:            public TextEdit getRootEdit() {
0633:                MultiTextEdit edit = null;
0634:                int length = this .textRegionEnd - this .textRegionStart + 1;
0635:                if (this .textRegionStart <= 0) {
0636:                    if (length <= 0) {
0637:                        edit = new MultiTextEdit(0, 0);
0638:                    } else {
0639:                        edit = new MultiTextEdit(0, this .textRegionEnd + 1);
0640:                    }
0641:                } else {
0642:                    edit = new MultiTextEdit(this .textRegionStart,
0643:                            this .textRegionEnd - this .textRegionStart + 1);
0644:                }
0645:                for (int i = 0, max = this .editsIndex; i < max; i++) {
0646:                    OptimizedReplaceEdit currentEdit = edits[i];
0647:                    if (isValidEdit(currentEdit)) {
0648:                        edit.addChild(new ReplaceEdit(currentEdit.offset,
0649:                                currentEdit.length, currentEdit.replacement));
0650:                    }
0651:                }
0652:                this .edits = null;
0653:                return edit;
0654:            }
0655:
0656:            public void handleLineTooLong() {
0657:                // search for closest breakable alignment, using tiebreak rules
0658:                // look for outermost breakable one
0659:                int relativeDepth = 0, outerMostDepth = -1;
0660:                Alignment targetAlignment = this .currentAlignment;
0661:                while (targetAlignment != null) {
0662:                    if (targetAlignment.tieBreakRule == Alignment.R_OUTERMOST
0663:                            && targetAlignment.couldBreak()) {
0664:                        outerMostDepth = relativeDepth;
0665:                    }
0666:                    targetAlignment = targetAlignment.enclosing;
0667:                    relativeDepth++;
0668:                }
0669:                if (outerMostDepth >= 0) {
0670:                    throw new AlignmentException(
0671:                            AlignmentException.LINE_TOO_LONG, outerMostDepth);
0672:                }
0673:                // look for innermost breakable one
0674:                relativeDepth = 0;
0675:                targetAlignment = this .currentAlignment;
0676:                while (targetAlignment != null) {
0677:                    if (targetAlignment.couldBreak()) {
0678:                        throw new AlignmentException(
0679:                                AlignmentException.LINE_TOO_LONG, relativeDepth);
0680:                    }
0681:                    targetAlignment = targetAlignment.enclosing;
0682:                    relativeDepth++;
0683:                }
0684:                // did not find any breakable location - proceed
0685:            }
0686:
0687:            /*
0688:             * Check if there is a NLS tag on this line. If yes, return true, returns false otherwise.
0689:             */
0690:            private boolean hasNLSTag(int sourceStart) {
0691:                // search the last comment where commentEnd < current lineEnd
0692:                if (this .lineEnds == null)
0693:                    return false;
0694:                int index = Arrays.binarySearch(this .lineEnds, sourceStart);
0695:                int currentLineEnd = this .getLineEnd(-index);
0696:                if (currentLineEnd != -1) {
0697:                    int commentIndex = getCommentIndex(currentLineEnd);
0698:                    if (commentIndex < 0) {
0699:                        commentIndex = -commentIndex - 2;
0700:                    }
0701:                    if (commentIndex >= 0
0702:                            && commentIndex < this .commentPositions.length) {
0703:                        int start = this .commentPositions[commentIndex][0];
0704:                        if (start < 0) {
0705:                            start = -start;
0706:                            // check that we are on the same line
0707:                            int lineIndexForComment = Arrays.binarySearch(
0708:                                    this .lineEnds, start);
0709:                            if (lineIndexForComment == index) {
0710:                                return CharOperation.indexOf(
0711:                                        Scanner.TAG_PREFIX,
0712:                                        this .scanner.source, true, start,
0713:                                        currentLineEnd) != -1;
0714:                            }
0715:                        }
0716:                    }
0717:                }
0718:                return false;
0719:            }
0720:
0721:            public void indent() {
0722:                this .indentationLevel += this .indentationSize;
0723:                this .numberOfIndentations++;
0724:            }
0725:
0726:            /**
0727:             * @param compilationUnitSource
0728:             */
0729:            public void initializeScanner(char[] compilationUnitSource) {
0730:                this .scanner.setSource(compilationUnitSource);
0731:                this .scannerEndPosition = compilationUnitSource.length;
0732:                this .scanner.resetTo(0, this .scannerEndPosition - 1);
0733:                this .edits = new OptimizedReplaceEdit[INITIAL_SIZE];
0734:            }
0735:
0736:            private boolean isOnFirstColumn(int start) {
0737:                if (this .lineEnds == null)
0738:                    return start == 0;
0739:                int index = Arrays.binarySearch(this .lineEnds, start);
0740:                // we want the line end of the previous line
0741:                int previousLineEnd = this .getLineEnd(-index - 1);
0742:                return previousLineEnd != -1 && previousLineEnd == start - 1;
0743:            }
0744:
0745:            private boolean isValidEdit(OptimizedReplaceEdit edit) {
0746:                final int editLength = edit.length;
0747:                final int editReplacementLength = edit.replacement.length();
0748:                final int editOffset = edit.offset;
0749:                if (editLength != 0) {
0750:                    if (this .textRegionStart <= editOffset
0751:                            && (editOffset + editLength - 1) <= this .textRegionEnd) {
0752:                        if (editReplacementLength != 0
0753:                                && editLength == editReplacementLength) {
0754:                            for (int i = editOffset, max = editOffset
0755:                                    + editLength; i < max; i++) {
0756:                                if (scanner.source[i] != edit.replacement
0757:                                        .charAt(i - editOffset)) {
0758:                                    return true;
0759:                                }
0760:                            }
0761:                            return false;
0762:                        } else {
0763:                            return true;
0764:                        }
0765:                    } else if (editOffset + editLength == this .textRegionStart) {
0766:                        int i = editOffset;
0767:                        for (int max = editOffset + editLength; i < max; i++) {
0768:                            int replacementStringIndex = i - editOffset;
0769:                            if (replacementStringIndex >= editReplacementLength
0770:                                    || scanner.source[i] != edit.replacement
0771:                                            .charAt(replacementStringIndex)) {
0772:                                break;
0773:                            }
0774:                        }
0775:                        if (i - editOffset != editReplacementLength
0776:                                && i != editOffset + editLength - 1) {
0777:                            edit.offset = textRegionStart;
0778:                            edit.length = 0;
0779:                            edit.replacement = edit.replacement.substring(i
0780:                                    - editOffset);
0781:                            return true;
0782:                        }
0783:                    }
0784:                } else if (this .textRegionStart <= editOffset
0785:                        && editOffset <= this .textRegionEnd) {
0786:                    return true;
0787:                } else if (editOffset == this .scannerEndPosition
0788:                        && editOffset == this .textRegionEnd + 1) {
0789:                    return true;
0790:                }
0791:                return false;
0792:            }
0793:
0794:            private void preserveEmptyLines(int count, int insertPosition) {
0795:                if (count > 0) {
0796:                    if (this .formatter.preferences.number_of_empty_lines_to_preserve != 0) {
0797:                        int linesToPreserve = Math
0798:                                .min(
0799:                                        count,
0800:                                        this .formatter.preferences.number_of_empty_lines_to_preserve);
0801:                        this .printEmptyLines(linesToPreserve, insertPosition);
0802:                    } else {
0803:                        printNewLine(insertPosition);
0804:                    }
0805:                }
0806:            }
0807:
0808:            private void print(char[] s, boolean considerSpaceIfAny) {
0809:                if (checkLineWrapping && s.length + column > this .pageWidth) {
0810:                    handleLineTooLong();
0811:                }
0812:                this .lastNumberOfNewLines = 0;
0813:                if (this .indentationLevel != 0) {
0814:                    printIndentationIfNecessary();
0815:                }
0816:                if (considerSpaceIfAny) {
0817:                    this .space();
0818:                }
0819:                if (this .pendingSpace) {
0820:                    this .addInsertEdit(this .scanner
0821:                            .getCurrentTokenStartPosition(), " "); //$NON-NLS-1$
0822:                }
0823:                this .pendingSpace = false;
0824:                this .needSpace = false;
0825:                column += s.length;
0826:                needSpace = true;
0827:            }
0828:
0829:            private void printBlockComment(char[] s, boolean isJavadoc) {
0830:                int currentTokenStartPosition = this .scanner
0831:                        .getCurrentTokenStartPosition();
0832:                int currentTokenEndPosition = this .scanner
0833:                        .getCurrentTokenEndPosition() + 1;
0834:
0835:                this .scanner.resetTo(currentTokenStartPosition,
0836:                        currentTokenEndPosition - 1);
0837:                int currentCharacter;
0838:                boolean isNewLine = false;
0839:                int start = currentTokenStartPosition;
0840:                int nextCharacterStart = currentTokenStartPosition;
0841:                int previousStart = currentTokenStartPosition;
0842:                boolean onFirstColumn = isOnFirstColumn(start);
0843:
0844:                boolean indentComment = false;
0845:                if (this .indentationLevel != 0) {
0846:                    if (isJavadoc
0847:                            || !this .formatter.preferences.never_indent_block_comments_on_first_column
0848:                            || !onFirstColumn) {
0849:                        indentComment = true;
0850:                        printIndentationIfNecessary();
0851:                    }
0852:                }
0853:                if (this .pendingSpace) {
0854:                    this .addInsertEdit(currentTokenStartPosition, " "); //$NON-NLS-1$
0855:                }
0856:                this .needSpace = false;
0857:                this .pendingSpace = false;
0858:
0859:                int currentCommentOffset = onFirstColumn ? 0
0860:                        : getCurrentCommentOffset(start);
0861:                boolean formatComment = (isJavadoc && formatJavadocComment)
0862:                        || (!isJavadoc && formatBlockComment);
0863:
0864:                while (nextCharacterStart <= currentTokenEndPosition
0865:                        && (currentCharacter = this .scanner.getNextChar()) != -1) {
0866:                    nextCharacterStart = this .scanner.currentPosition;
0867:
0868:                    switch (currentCharacter) {
0869:                    case '\r':
0870:                        start = previousStart;
0871:                        isNewLine = true;
0872:                        if (this .scanner.getNextChar('\n')) {
0873:                            currentCharacter = '\n';
0874:                            nextCharacterStart = this .scanner.currentPosition;
0875:                        }
0876:                        break;
0877:                    case '\n':
0878:                        start = previousStart;
0879:                        isNewLine = true;
0880:                        nextCharacterStart = this .scanner.currentPosition;
0881:                        break;
0882:                    default:
0883:                        if (isNewLine) {
0884:                            this .column = 1;
0885:                            this .line++;
0886:                            isNewLine = false;
0887:
0888:                            StringBuffer buffer = new StringBuffer();
0889:                            if (onFirstColumn) {
0890:                                // simply insert indentation if necessary
0891:                                buffer.append(this .lineSeparator);
0892:                                if (indentComment) {
0893:                                    printIndentationIfNecessary(buffer);
0894:                                }
0895:                                if (formatComment) {
0896:                                    if (ScannerHelper
0897:                                            .isWhitespace((char) currentCharacter)) {
0898:                                        int previousStartPosition = this .scanner.currentPosition;
0899:                                        while (currentCharacter != -1
0900:                                                && currentCharacter != '\r'
0901:                                                && currentCharacter != '\n'
0902:                                                && ScannerHelper
0903:                                                        .isWhitespace((char) currentCharacter)) {
0904:                                            previousStart = nextCharacterStart;
0905:                                            previousStartPosition = this .scanner.currentPosition;
0906:                                            currentCharacter = this .scanner
0907:                                                    .getNextChar();
0908:                                            nextCharacterStart = this .scanner.currentPosition;
0909:                                        }
0910:                                        if (currentCharacter == '\r'
0911:                                                || currentCharacter == '\n') {
0912:                                            nextCharacterStart = previousStartPosition;
0913:                                        }
0914:                                    }
0915:                                    if (currentCharacter != '\r'
0916:                                            && currentCharacter != '\n') {
0917:                                        buffer.append(' ');
0918:                                    }
0919:                                }
0920:                            } else {
0921:                                if (ScannerHelper
0922:                                        .isWhitespace((char) currentCharacter)) {
0923:                                    int previousStartPosition = this .scanner.currentPosition;
0924:                                    int count = 0;
0925:                                    loop: while (currentCharacter != -1
0926:                                            && currentCharacter != '\r'
0927:                                            && currentCharacter != '\n'
0928:                                            && ScannerHelper
0929:                                                    .isWhitespace((char) currentCharacter)) {
0930:                                        if (count >= currentCommentOffset) {
0931:                                            break loop;
0932:                                        }
0933:                                        previousStart = nextCharacterStart;
0934:                                        previousStartPosition = this .scanner.currentPosition;
0935:                                        switch (currentCharacter) {
0936:                                        case '\t':
0937:                                            count += this .tabLength;
0938:                                            break;
0939:                                        default:
0940:                                            count++;
0941:                                        }
0942:                                        currentCharacter = this .scanner
0943:                                                .getNextChar();
0944:                                        nextCharacterStart = this .scanner.currentPosition;
0945:                                    }
0946:                                    if (currentCharacter == '\r'
0947:                                            || currentCharacter == '\n') {
0948:                                        nextCharacterStart = previousStartPosition;
0949:                                    }
0950:                                }
0951:                                buffer.append(this .lineSeparator);
0952:                                if (indentComment) {
0953:                                    printIndentationIfNecessary(buffer);
0954:                                }
0955:                                if (formatComment) {
0956:                                    int previousStartTemp = previousStart;
0957:                                    int nextCharacterStartTemp = nextCharacterStart;
0958:                                    while (currentCharacter != -1
0959:                                            && currentCharacter != '\r'
0960:                                            && currentCharacter != '\n'
0961:                                            && ScannerHelper
0962:                                                    .isWhitespace((char) currentCharacter)) {
0963:                                        previousStart = nextCharacterStart;
0964:                                        currentCharacter = this .scanner
0965:                                                .getNextChar();
0966:                                        nextCharacterStart = this .scanner.currentPosition;
0967:                                    }
0968:                                    if (currentCharacter == '*') {
0969:                                        buffer.append(' ');
0970:                                    } else {
0971:                                        previousStart = previousStartTemp;
0972:                                        nextCharacterStart = nextCharacterStartTemp;
0973:                                    }
0974:                                    this .scanner.currentPosition = nextCharacterStart;
0975:                                }
0976:                            }
0977:                            addReplaceEdit(start, previousStart - 1, String
0978:                                    .valueOf(buffer));
0979:                        } else {
0980:                            this .column += (nextCharacterStart - previousStart);
0981:                        }
0982:                    }
0983:                    previousStart = nextCharacterStart;
0984:                    this .scanner.currentPosition = nextCharacterStart;
0985:                }
0986:                this .lastNumberOfNewLines = 0;
0987:                needSpace = false;
0988:                this .scanner.resetTo(currentTokenEndPosition,
0989:                        this .scannerEndPosition - 1);
0990:                if (isJavadoc) {
0991:                    printNewLine();
0992:                }
0993:            }
0994:
0995:            public void printEndOfCompilationUnit() {
0996:                try {
0997:                    // if we have a space between two tokens we ensure it will be dumped in the formatted string
0998:                    int currentTokenStartPosition = this .scanner.currentPosition;
0999:                    boolean hasComment = false;
1000:                    boolean hasLineComment = false;
1001:                    boolean hasWhitespace = false;
1002:                    int count = 0;
1003:                    while (true) {
1004:                        this .currentToken = this .scanner.getNextToken();
1005:                        switch (this .currentToken) {
1006:                        case TerminalTokens.TokenNameWHITESPACE:
1007:                            char[] whiteSpaces = this .scanner
1008:                                    .getCurrentTokenSource();
1009:                            count = 0;
1010:                            for (int i = 0, max = whiteSpaces.length; i < max; i++) {
1011:                                switch (whiteSpaces[i]) {
1012:                                case '\r':
1013:                                    if ((i + 1) < max) {
1014:                                        if (whiteSpaces[i + 1] == '\n') {
1015:                                            i++;
1016:                                        }
1017:                                    }
1018:                                    count++;
1019:                                    break;
1020:                                case '\n':
1021:                                    count++;
1022:                                }
1023:                            }
1024:                            if (count == 0) {
1025:                                hasWhitespace = true;
1026:                                addDeleteEdit(this .scanner
1027:                                        .getCurrentTokenStartPosition(),
1028:                                        this .scanner
1029:                                                .getCurrentTokenEndPosition());
1030:                            } else if (hasComment) {
1031:                                if (count == 1) {
1032:                                    this .printNewLine(this .scanner
1033:                                            .getCurrentTokenStartPosition());
1034:                                } else {
1035:                                    preserveEmptyLines(count - 1, this .scanner
1036:                                            .getCurrentTokenStartPosition());
1037:                                }
1038:                                addDeleteEdit(this .scanner
1039:                                        .getCurrentTokenStartPosition(),
1040:                                        this .scanner
1041:                                                .getCurrentTokenEndPosition());
1042:                            } else if (hasLineComment) {
1043:                                this .preserveEmptyLines(count, this .scanner
1044:                                        .getCurrentTokenStartPosition());
1045:                                addDeleteEdit(this .scanner
1046:                                        .getCurrentTokenStartPosition(),
1047:                                        this .scanner
1048:                                                .getCurrentTokenEndPosition());
1049:                            } else {
1050:                                addDeleteEdit(this .scanner
1051:                                        .getCurrentTokenStartPosition(),
1052:                                        this .scanner
1053:                                                .getCurrentTokenEndPosition());
1054:                            }
1055:                            currentTokenStartPosition = this .scanner.currentPosition;
1056:                            break;
1057:                        case TerminalTokens.TokenNameCOMMENT_LINE:
1058:                            if (count >= 1) {
1059:                                if (count > 1) {
1060:                                    preserveEmptyLines(count - 1, this .scanner
1061:                                            .getCurrentTokenStartPosition());
1062:                                } else if (count == 1) {
1063:                                    printNewLine(this .scanner
1064:                                            .getCurrentTokenStartPosition());
1065:                                }
1066:                            } else if (hasWhitespace) {
1067:                                space();
1068:                            }
1069:                            hasWhitespace = false;
1070:                            this .printLineComment(this .scanner
1071:                                    .getRawTokenSource());
1072:                            currentTokenStartPosition = this .scanner.currentPosition;
1073:                            hasLineComment = true;
1074:                            count = 0;
1075:                            break;
1076:                        case TerminalTokens.TokenNameCOMMENT_BLOCK:
1077:                            if (count >= 1) {
1078:                                if (count > 1) {
1079:                                    preserveEmptyLines(count - 1, this .scanner
1080:                                            .getCurrentTokenStartPosition());
1081:                                } else if (count == 1) {
1082:                                    printNewLine(this .scanner
1083:                                            .getCurrentTokenStartPosition());
1084:                                }
1085:                            } else if (hasWhitespace) {
1086:                                space();
1087:                            }
1088:                            hasWhitespace = false;
1089:                            this .printBlockComment(this .scanner
1090:                                    .getRawTokenSource(), false);
1091:                            currentTokenStartPosition = this .scanner.currentPosition;
1092:                            hasLineComment = false;
1093:                            hasComment = true;
1094:                            count = 0;
1095:                            break;
1096:                        case TerminalTokens.TokenNameCOMMENT_JAVADOC:
1097:                            if (count >= 1) {
1098:                                if (count > 1) {
1099:                                    preserveEmptyLines(count - 1, this .scanner
1100:                                            .getCurrentTokenStartPosition());
1101:                                } else if (count == 1) {
1102:                                    printNewLine(this .scanner
1103:                                            .getCurrentTokenStartPosition());
1104:                                }
1105:                            } else if (hasWhitespace) {
1106:                                space();
1107:                            }
1108:                            hasWhitespace = false;
1109:                            this .printBlockComment(this .scanner
1110:                                    .getRawTokenSource(), true);
1111:                            currentTokenStartPosition = this .scanner.currentPosition;
1112:                            hasLineComment = false;
1113:                            hasComment = true;
1114:                            count = 0;
1115:                            break;
1116:                        case TerminalTokens.TokenNameSEMICOLON:
1117:                            char[] currentTokenSource = this .scanner
1118:                                    .getRawTokenSource();
1119:                            this 
1120:                                    .print(
1121:                                            currentTokenSource,
1122:                                            this .formatter.preferences.insert_space_before_semicolon);
1123:                            break;
1124:                        case TerminalTokens.TokenNameEOF:
1125:                            if (count >= 1
1126:                                    || this .formatter.preferences.insert_new_line_at_end_of_file_if_missing) {
1127:                                this .printNewLine(this .scannerEndPosition);
1128:                            }
1129:                            return;
1130:                        default:
1131:                            // step back one token
1132:                            this .scanner.resetTo(currentTokenStartPosition,
1133:                                    this .scannerEndPosition - 1);
1134:                            return;
1135:                        }
1136:                    }
1137:                } catch (InvalidInputException e) {
1138:                    throw new AbortFormatting(e);
1139:                }
1140:            }
1141:
1142:            public void printComment() {
1143:                try {
1144:                    // if we have a space between two tokens we ensure it will be dumped in the formatted string
1145:                    int currentTokenStartPosition = this .scanner.currentPosition;
1146:                    boolean hasComment = false;
1147:                    boolean hasLineComment = false;
1148:                    boolean hasWhitespace = false;
1149:                    int count = 0;
1150:                    while ((this .currentToken = this .scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
1151:                        switch (this .currentToken) {
1152:                        case TerminalTokens.TokenNameWHITESPACE:
1153:                            char[] whiteSpaces = this .scanner
1154:                                    .getCurrentTokenSource();
1155:                            count = 0;
1156:                            for (int i = 0, max = whiteSpaces.length; i < max; i++) {
1157:                                switch (whiteSpaces[i]) {
1158:                                case '\r':
1159:                                    if ((i + 1) < max) {
1160:                                        if (whiteSpaces[i + 1] == '\n') {
1161:                                            i++;
1162:                                        }
1163:                                    }
1164:                                    count++;
1165:                                    break;
1166:                                case '\n':
1167:                                    count++;
1168:                                }
1169:                            }
1170:                            if (count == 0) {
1171:                                hasWhitespace = true;
1172:                                addDeleteEdit(this .scanner
1173:                                        .getCurrentTokenStartPosition(),
1174:                                        this .scanner
1175:                                                .getCurrentTokenEndPosition());
1176:                            } else if (hasComment) {
1177:                                if (count == 1) {
1178:                                    this .printNewLine(this .scanner
1179:                                            .getCurrentTokenStartPosition());
1180:                                } else {
1181:                                    preserveEmptyLines(count - 1, this .scanner
1182:                                            .getCurrentTokenStartPosition());
1183:                                }
1184:                                addDeleteEdit(this .scanner
1185:                                        .getCurrentTokenStartPosition(),
1186:                                        this .scanner
1187:                                                .getCurrentTokenEndPosition());
1188:                            } else if (hasLineComment) {
1189:                                this .preserveEmptyLines(count, this .scanner
1190:                                        .getCurrentTokenStartPosition());
1191:                                addDeleteEdit(this .scanner
1192:                                        .getCurrentTokenStartPosition(),
1193:                                        this .scanner
1194:                                                .getCurrentTokenEndPosition());
1195:                            } else if (count != 0
1196:                                    && this .formatter.preferences.number_of_empty_lines_to_preserve != 0) {
1197:                                addReplaceEdit(this .scanner
1198:                                        .getCurrentTokenStartPosition(),
1199:                                        this .scanner
1200:                                                .getCurrentTokenEndPosition(),
1201:                                        this .getPreserveEmptyLines(count - 1));
1202:                            } else {
1203:                                addDeleteEdit(this .scanner
1204:                                        .getCurrentTokenStartPosition(),
1205:                                        this .scanner
1206:                                                .getCurrentTokenEndPosition());
1207:                            }
1208:                            currentTokenStartPosition = this .scanner.currentPosition;
1209:                            break;
1210:                        case TerminalTokens.TokenNameCOMMENT_LINE:
1211:                            if (count >= 1) {
1212:                                if (count > 1) {
1213:                                    preserveEmptyLines(count - 1, this .scanner
1214:                                            .getCurrentTokenStartPosition());
1215:                                } else if (count == 1) {
1216:                                    printNewLine(this .scanner
1217:                                            .getCurrentTokenStartPosition());
1218:                                }
1219:                            } else if (hasWhitespace) {
1220:                                space();
1221:                            }
1222:                            hasWhitespace = false;
1223:                            this .printLineComment(this .scanner
1224:                                    .getRawTokenSource());
1225:                            currentTokenStartPosition = this .scanner.currentPosition;
1226:                            hasLineComment = true;
1227:                            count = 0;
1228:                            break;
1229:                        case TerminalTokens.TokenNameCOMMENT_BLOCK:
1230:                            if (count >= 1) {
1231:                                if (count > 1) {
1232:                                    preserveEmptyLines(count - 1, this .scanner
1233:                                            .getCurrentTokenStartPosition());
1234:                                } else if (count == 1) {
1235:                                    printNewLine(this .scanner
1236:                                            .getCurrentTokenStartPosition());
1237:                                }
1238:                            } else if (hasWhitespace) {
1239:                                space();
1240:                            }
1241:                            hasWhitespace = false;
1242:                            this .printBlockComment(this .scanner
1243:                                    .getRawTokenSource(), false);
1244:                            currentTokenStartPosition = this .scanner.currentPosition;
1245:                            hasLineComment = false;
1246:                            hasComment = true;
1247:                            count = 0;
1248:                            break;
1249:                        case TerminalTokens.TokenNameCOMMENT_JAVADOC:
1250:                            if (count >= 1) {
1251:                                if (count > 1) {
1252:                                    preserveEmptyLines(count - 1, this .scanner
1253:                                            .getCurrentTokenStartPosition());
1254:                                } else if (count == 1) {
1255:                                    printNewLine(this .scanner
1256:                                            .getCurrentTokenStartPosition());
1257:                                }
1258:                            } else if (hasWhitespace) {
1259:                                space();
1260:                            }
1261:                            hasWhitespace = false;
1262:                            this .printBlockComment(this .scanner
1263:                                    .getRawTokenSource(), true);
1264:                            currentTokenStartPosition = this .scanner.currentPosition;
1265:                            hasLineComment = false;
1266:                            hasComment = true;
1267:                            count = 0;
1268:                            break;
1269:                        default:
1270:                            // step back one token
1271:                            this .scanner.resetTo(currentTokenStartPosition,
1272:                                    this .scannerEndPosition - 1);
1273:                            return;
1274:                        }
1275:                    }
1276:                } catch (InvalidInputException e) {
1277:                    throw new AbortFormatting(e);
1278:                }
1279:            }
1280:
1281:            private void printLineComment(char[] s) {
1282:                int currentTokenStartPosition = this .scanner
1283:                        .getCurrentTokenStartPosition();
1284:                int currentTokenEndPosition = this .scanner
1285:                        .getCurrentTokenEndPosition() + 1;
1286:                if (CharOperation.indexOf(Scanner.TAG_PREFIX,
1287:                        this .scanner.source, true, currentTokenStartPosition,
1288:                        currentTokenEndPosition) != -1) {
1289:                    this .nlsTagCounter = 0;
1290:                }
1291:                this .scanner.resetTo(currentTokenStartPosition,
1292:                        currentTokenEndPosition - 1);
1293:                int currentCharacter;
1294:                int start = currentTokenStartPosition;
1295:                int nextCharacterStart = currentTokenStartPosition;
1296:
1297:                if (this .indentationLevel != 0) {
1298:                    if (!this .formatter.preferences.never_indent_line_comments_on_first_column
1299:                            || !isOnFirstColumn(start)) {
1300:                        printIndentationIfNecessary();
1301:                    }
1302:                }
1303:                if (this .pendingSpace) {
1304:                    this .addInsertEdit(currentTokenStartPosition, " "); //$NON-NLS-1$
1305:                }
1306:                this .needSpace = false;
1307:                this .pendingSpace = false;
1308:                int previousStart = currentTokenStartPosition;
1309:
1310:                loop: while (nextCharacterStart <= currentTokenEndPosition
1311:                        && (currentCharacter = this .scanner.getNextChar()) != -1) {
1312:                    nextCharacterStart = this .scanner.currentPosition;
1313:
1314:                    switch (currentCharacter) {
1315:                    case '\r':
1316:                        start = previousStart;
1317:                        break loop;
1318:                    case '\n':
1319:                        start = previousStart;
1320:                        break loop;
1321:                    }
1322:                    previousStart = nextCharacterStart;
1323:                }
1324:                if (start != currentTokenStartPosition) {
1325:                    // this means that the line comment doesn't end the file
1326:                    addReplaceEdit(start, currentTokenEndPosition - 1,
1327:                            lineSeparator);
1328:                    this .line++;
1329:                    this .column = 1;
1330:                    this .lastNumberOfNewLines = 1;
1331:                }
1332:                this .needSpace = false;
1333:                this .pendingSpace = false;
1334:                // realign to the proper value
1335:                if (this .currentAlignment != null) {
1336:                    if (this .memberAlignment != null) {
1337:                        // select the last alignment
1338:                        if (this .currentAlignment.location.inputOffset > this .memberAlignment.location.inputOffset) {
1339:                            if (this .currentAlignment.couldBreak()
1340:                                    && this .currentAlignment.wasSplit) {
1341:                                this .currentAlignment.performFragmentEffect();
1342:                            }
1343:                        } else {
1344:                            this .indentationLevel = Math.max(
1345:                                    this .indentationLevel,
1346:                                    this .memberAlignment.breakIndentationLevel);
1347:                        }
1348:                    } else if (this .currentAlignment.couldBreak()
1349:                            && this .currentAlignment.wasSplit) {
1350:                        this .currentAlignment.performFragmentEffect();
1351:                    }
1352:                }
1353:                this .scanner.resetTo(currentTokenEndPosition,
1354:                        this .scannerEndPosition - 1);
1355:            }
1356:
1357:            public void printEmptyLines(int linesNumber) {
1358:                this .printEmptyLines(linesNumber, this .scanner
1359:                        .getCurrentTokenEndPosition() + 1);
1360:            }
1361:
1362:            private void printEmptyLines(int linesNumber, int insertPosition) {
1363:                final String buffer = getEmptyLines(linesNumber);
1364:                if (Util.EMPTY_STRING == buffer)
1365:                    return;
1366:
1367:                addInsertEdit(insertPosition, buffer);
1368:            }
1369:
1370:            void printIndentationIfNecessary() {
1371:                StringBuffer buffer = new StringBuffer();
1372:                printIndentationIfNecessary(buffer);
1373:                if (buffer.length() > 0) {
1374:                    addInsertEdit(this .scanner.getCurrentTokenStartPosition(),
1375:                            buffer.toString());
1376:                    this .pendingSpace = false;
1377:                }
1378:            }
1379:
1380:            private void printIndentationIfNecessary(StringBuffer buffer) {
1381:                switch (this .tabChar) {
1382:                case DefaultCodeFormatterOptions.TAB:
1383:                    boolean useTabsForLeadingIndents = this .useTabsOnlyForLeadingIndents;
1384:                    int numberOfLeadingIndents = this .numberOfIndentations;
1385:                    int indentationsAsTab = 0;
1386:                    if (useTabsForLeadingIndents) {
1387:                        while (this .column <= this .indentationLevel) {
1388:                            if (indentationsAsTab < numberOfLeadingIndents) {
1389:                                buffer.append('\t');
1390:                                indentationsAsTab++;
1391:                                int complement = this .tabLength
1392:                                        - ((this .column - 1) % this .tabLength); // amount of space
1393:                                this .column += complement;
1394:                                this .needSpace = false;
1395:                            } else {
1396:                                buffer.append(' ');
1397:                                this .column++;
1398:                                this .needSpace = false;
1399:                            }
1400:                        }
1401:                    } else {
1402:                        while (this .column <= this .indentationLevel) {
1403:                            buffer.append('\t');
1404:                            int complement = this .tabLength
1405:                                    - ((this .column - 1) % this .tabLength); // amount of space
1406:                            this .column += complement;
1407:                            this .needSpace = false;
1408:                        }
1409:                    }
1410:                    break;
1411:                case DefaultCodeFormatterOptions.SPACE:
1412:                    while (this .column <= this .indentationLevel) {
1413:                        buffer.append(' ');
1414:                        this .column++;
1415:                        this .needSpace = false;
1416:                    }
1417:                    break;
1418:                case DefaultCodeFormatterOptions.MIXED:
1419:                    useTabsForLeadingIndents = this .useTabsOnlyForLeadingIndents;
1420:                    numberOfLeadingIndents = this .numberOfIndentations;
1421:                    indentationsAsTab = 0;
1422:                    if (useTabsForLeadingIndents) {
1423:                        final int columnForLeadingIndents = numberOfLeadingIndents
1424:                                * this .indentationSize;
1425:                        while (this .column <= this .indentationLevel) {
1426:                            if (this .column <= columnForLeadingIndents) {
1427:                                if ((this .column - 1 + this .tabLength) <= this .indentationLevel) {
1428:                                    buffer.append('\t');
1429:                                    this .column += this .tabLength;
1430:                                } else if ((this .column - 1 + this .indentationSize) <= this .indentationLevel) {
1431:                                    // print one indentation
1432:                                    for (int i = 0, max = this .indentationSize; i < max; i++) {
1433:                                        buffer.append(' ');
1434:                                        this .column++;
1435:                                    }
1436:                                } else {
1437:                                    buffer.append(' ');
1438:                                    this .column++;
1439:                                }
1440:                            } else {
1441:                                for (int i = this .column, max = this .indentationLevel; i <= max; i++) {
1442:                                    buffer.append(' ');
1443:                                    this .column++;
1444:                                }
1445:                            }
1446:                            this .needSpace = false;
1447:                        }
1448:                    } else {
1449:                        while (this .column <= this .indentationLevel) {
1450:                            if ((this .column - 1 + this .tabLength) <= this .indentationLevel) {
1451:                                buffer.append('\t');
1452:                                this .column += this .tabLength;
1453:                            } else if ((this .column - 1 + this .indentationSize) <= this .indentationLevel) {
1454:                                // print one indentation
1455:                                for (int i = 0, max = this .indentationSize; i < max; i++) {
1456:                                    buffer.append(' ');
1457:                                    this .column++;
1458:                                }
1459:                            } else {
1460:                                buffer.append(' ');
1461:                                this .column++;
1462:                            }
1463:                            this .needSpace = false;
1464:                        }
1465:                    }
1466:                    break;
1467:                }
1468:            }
1469:
1470:            public void printModifiers(Annotation[] annotations,
1471:                    ASTVisitor visitor) {
1472:                try {
1473:                    int annotationsLength = annotations != null ? annotations.length
1474:                            : 0;
1475:                    int annotationsIndex = 0;
1476:                    boolean isFirstModifier = true;
1477:                    int currentTokenStartPosition = this .scanner.currentPosition;
1478:                    boolean hasComment = false;
1479:                    boolean hasModifiers = false;
1480:                    while ((this .currentToken = this .scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
1481:                        switch (this .currentToken) {
1482:                        case TerminalTokens.TokenNamepublic:
1483:                        case TerminalTokens.TokenNameprotected:
1484:                        case TerminalTokens.TokenNameprivate:
1485:                        case TerminalTokens.TokenNamestatic:
1486:                        case TerminalTokens.TokenNameabstract:
1487:                        case TerminalTokens.TokenNamefinal:
1488:                        case TerminalTokens.TokenNamenative:
1489:                        case TerminalTokens.TokenNamesynchronized:
1490:                        case TerminalTokens.TokenNametransient:
1491:                        case TerminalTokens.TokenNamevolatile:
1492:                        case TerminalTokens.TokenNamestrictfp:
1493:                            hasModifiers = true;
1494:                            this .print(this .scanner.getRawTokenSource(),
1495:                                    !isFirstModifier);
1496:                            isFirstModifier = false;
1497:                            currentTokenStartPosition = this .scanner.currentPosition;
1498:                            break;
1499:                        case TerminalTokens.TokenNameAT:
1500:                            hasModifiers = true;
1501:                            if (!isFirstModifier) {
1502:                                this .space();
1503:                            }
1504:                            this .scanner.resetTo(this .scanner
1505:                                    .getCurrentTokenStartPosition(),
1506:                                    this .scannerEndPosition - 1);
1507:                            if (annotationsIndex < annotationsLength) {
1508:                                annotations[annotationsIndex++].traverse(
1509:                                        visitor, (BlockScope) null);
1510:                                if (this .formatter.preferences.insert_new_line_after_annotation) {
1511:                                    this .printNewLine();
1512:                                }
1513:                            } else {
1514:                                return;
1515:                            }
1516:                            isFirstModifier = false;
1517:                            currentTokenStartPosition = this .scanner.currentPosition;
1518:                            break;
1519:                        case TerminalTokens.TokenNameCOMMENT_BLOCK:
1520:                            this .printBlockComment(this .scanner
1521:                                    .getRawTokenSource(), false);
1522:                            currentTokenStartPosition = this .scanner.currentPosition;
1523:                            hasComment = true;
1524:                            break;
1525:                        case TerminalTokens.TokenNameCOMMENT_JAVADOC:
1526:                            this .printBlockComment(this .scanner
1527:                                    .getRawTokenSource(), true);
1528:                            currentTokenStartPosition = this .scanner.currentPosition;
1529:                            hasComment = true;
1530:                            break;
1531:                        case TerminalTokens.TokenNameCOMMENT_LINE:
1532:                            this .printLineComment(this .scanner
1533:                                    .getRawTokenSource());
1534:                            currentTokenStartPosition = this .scanner.currentPosition;
1535:                            break;
1536:                        case TerminalTokens.TokenNameWHITESPACE:
1537:                            addDeleteEdit(this .scanner
1538:                                    .getCurrentTokenStartPosition(),
1539:                                    this .scanner.getCurrentTokenEndPosition());
1540:                            int count = 0;
1541:                            char[] whiteSpaces = this .scanner
1542:                                    .getCurrentTokenSource();
1543:                            for (int i = 0, max = whiteSpaces.length; i < max; i++) {
1544:                                switch (whiteSpaces[i]) {
1545:                                case '\r':
1546:                                    if ((i + 1) < max) {
1547:                                        if (whiteSpaces[i + 1] == '\n') {
1548:                                            i++;
1549:                                        }
1550:                                    }
1551:                                    count++;
1552:                                    break;
1553:                                case '\n':
1554:                                    count++;
1555:                                }
1556:                            }
1557:                            if (count >= 1 && hasComment) {
1558:                                printNewLine();
1559:                            }
1560:                            currentTokenStartPosition = this .scanner.currentPosition;
1561:                            hasComment = false;
1562:                            break;
1563:                        default:
1564:                            if (hasModifiers) {
1565:                                this .space();
1566:                            }
1567:                            // step back one token
1568:                            this .scanner.resetTo(currentTokenStartPosition,
1569:                                    this .scannerEndPosition - 1);
1570:                            return;
1571:                        }
1572:                    }
1573:                } catch (InvalidInputException e) {
1574:                    throw new AbortFormatting(e);
1575:                }
1576:            }
1577:
1578:            public void printNewLine() {
1579:                if (this .nlsTagCounter > 0) {
1580:                    return;
1581:                }
1582:                if (lastNumberOfNewLines >= 1) {
1583:                    column = 1; // ensure that the scribe is at the beginning of a new line
1584:                    return;
1585:                }
1586:                addInsertEdit(this .scanner.getCurrentTokenEndPosition() + 1,
1587:                        this .lineSeparator);
1588:                line++;
1589:                lastNumberOfNewLines = 1;
1590:                column = 1;
1591:                needSpace = false;
1592:                this .pendingSpace = false;
1593:            }
1594:
1595:            public void printNewLine(int insertPosition) {
1596:                if (this .nlsTagCounter > 0) {
1597:                    return;
1598:                }
1599:                if (lastNumberOfNewLines >= 1) {
1600:                    column = 1; // ensure that the scribe is at the beginning of a new line
1601:                    return;
1602:                }
1603:                addInsertEdit(insertPosition, this .lineSeparator);
1604:                line++;
1605:                lastNumberOfNewLines = 1;
1606:                column = 1;
1607:                needSpace = false;
1608:                this .pendingSpace = false;
1609:            }
1610:
1611:            public void printNextToken(int expectedTokenType) {
1612:                printNextToken(expectedTokenType, false);
1613:            }
1614:
1615:            public void printNextToken(int expectedTokenType,
1616:                    boolean considerSpaceIfAny) {
1617:                printComment();
1618:                try {
1619:                    this .currentToken = this .scanner.getNextToken();
1620:                    char[] currentTokenSource = this .scanner
1621:                            .getRawTokenSource();
1622:                    if (expectedTokenType != this .currentToken) {
1623:                        throw new AbortFormatting(
1624:                                "unexpected token type, expecting:" + expectedTokenType + ", actual:" + this .currentToken);//$NON-NLS-1$//$NON-NLS-2$
1625:                    }
1626:                    this .print(currentTokenSource, considerSpaceIfAny);
1627:                } catch (InvalidInputException e) {
1628:                    throw new AbortFormatting(e);
1629:                }
1630:            }
1631:
1632:            public void printNextToken(int[] expectedTokenTypes) {
1633:                printNextToken(expectedTokenTypes, false);
1634:            }
1635:
1636:            public void printNextToken(int[] expectedTokenTypes,
1637:                    boolean considerSpaceIfAny) {
1638:                printComment();
1639:                try {
1640:                    this .currentToken = this .scanner.getNextToken();
1641:                    char[] currentTokenSource = this .scanner
1642:                            .getRawTokenSource();
1643:                    if (Arrays.binarySearch(expectedTokenTypes,
1644:                            this .currentToken) < 0) {
1645:                        StringBuffer expectations = new StringBuffer(5);
1646:                        for (int i = 0; i < expectedTokenTypes.length; i++) {
1647:                            if (i > 0) {
1648:                                expectations.append(',');
1649:                            }
1650:                            expectations.append(expectedTokenTypes[i]);
1651:                        }
1652:                        throw new AbortFormatting(
1653:                                "unexpected token type, expecting:[" + expectations.toString() + "], actual:" + this .currentToken);//$NON-NLS-1$//$NON-NLS-2$
1654:                    }
1655:                    this .print(currentTokenSource, considerSpaceIfAny);
1656:                } catch (InvalidInputException e) {
1657:                    throw new AbortFormatting(e);
1658:                }
1659:            }
1660:
1661:            public void printArrayQualifiedReference(int numberOfTokens,
1662:                    int sourceEnd) {
1663:                int currentTokenStartPosition = this .scanner.currentPosition;
1664:                int numberOfIdentifiers = 0;
1665:                try {
1666:                    do {
1667:                        this .printComment();
1668:                        switch (this .currentToken = this .scanner.getNextToken()) {
1669:                        case TerminalTokens.TokenNameEOF:
1670:                            return;
1671:                        case TerminalTokens.TokenNameWHITESPACE:
1672:                            addDeleteEdit(this .scanner
1673:                                    .getCurrentTokenStartPosition(),
1674:                                    this .scanner.getCurrentTokenEndPosition());
1675:                            currentTokenStartPosition = this .scanner.currentPosition;
1676:                            break;
1677:                        case TerminalTokens.TokenNameCOMMENT_BLOCK:
1678:                        case TerminalTokens.TokenNameCOMMENT_JAVADOC:
1679:                            this .printBlockComment(this .scanner
1680:                                    .getRawTokenSource(), false);
1681:                            currentTokenStartPosition = this .scanner.currentPosition;
1682:                            break;
1683:                        case TerminalTokens.TokenNameCOMMENT_LINE:
1684:                            this .printLineComment(this .scanner
1685:                                    .getRawTokenSource());
1686:                            currentTokenStartPosition = this .scanner.currentPosition;
1687:                            break;
1688:                        case TerminalTokens.TokenNameIdentifier:
1689:                            this .print(this .scanner.getRawTokenSource(), false);
1690:                            currentTokenStartPosition = this .scanner.currentPosition;
1691:                            if (++numberOfIdentifiers == numberOfTokens) {
1692:                                this .scanner.resetTo(currentTokenStartPosition,
1693:                                        this .scannerEndPosition - 1);
1694:                                return;
1695:                            }
1696:                            break;
1697:                        case TerminalTokens.TokenNameDOT:
1698:                            this .print(this .scanner.getRawTokenSource(), false);
1699:                            currentTokenStartPosition = this .scanner.currentPosition;
1700:                            break;
1701:                        default:
1702:                            this .scanner.resetTo(currentTokenStartPosition,
1703:                                    this .scannerEndPosition - 1);
1704:                            return;
1705:                        }
1706:                    } while (this .scanner.currentPosition <= sourceEnd);
1707:                } catch (InvalidInputException e) {
1708:                    throw new AbortFormatting(e);
1709:                }
1710:            }
1711:
1712:            public void printQualifiedReference(int sourceEnd) {
1713:                int currentTokenStartPosition = this .scanner.currentPosition;
1714:                try {
1715:                    do {
1716:                        this .printComment();
1717:                        switch (this .currentToken = this .scanner.getNextToken()) {
1718:                        case TerminalTokens.TokenNameEOF:
1719:                            return;
1720:                        case TerminalTokens.TokenNameWHITESPACE:
1721:                            addDeleteEdit(this .scanner
1722:                                    .getCurrentTokenStartPosition(),
1723:                                    this .scanner.getCurrentTokenEndPosition());
1724:                            currentTokenStartPosition = this .scanner.currentPosition;
1725:                            break;
1726:                        case TerminalTokens.TokenNameCOMMENT_BLOCK:
1727:                        case TerminalTokens.TokenNameCOMMENT_JAVADOC:
1728:                            this .printBlockComment(this .scanner
1729:                                    .getRawTokenSource(), false);
1730:                            currentTokenStartPosition = this .scanner.currentPosition;
1731:                            break;
1732:                        case TerminalTokens.TokenNameCOMMENT_LINE:
1733:                            this .printLineComment(this .scanner
1734:                                    .getRawTokenSource());
1735:                            currentTokenStartPosition = this .scanner.currentPosition;
1736:                            break;
1737:                        case TerminalTokens.TokenNameIdentifier:
1738:                        case TerminalTokens.TokenNameDOT:
1739:                            this .print(this .scanner.getRawTokenSource(), false);
1740:                            currentTokenStartPosition = this .scanner.currentPosition;
1741:                            break;
1742:                        default:
1743:                            this .scanner.resetTo(currentTokenStartPosition,
1744:                                    this .scannerEndPosition - 1);
1745:                            return;
1746:                        }
1747:                    } while (this .scanner.currentPosition <= sourceEnd);
1748:                } catch (InvalidInputException e) {
1749:                    throw new AbortFormatting(e);
1750:                }
1751:            }
1752:
1753:            private void printRule(StringBuffer stringBuffer) {
1754:                for (int i = 0; i < this .pageWidth; i++) {
1755:                    if ((i % this .tabLength) == 0) {
1756:                        stringBuffer.append('+');
1757:                    } else {
1758:                        stringBuffer.append('-');
1759:                    }
1760:                }
1761:                stringBuffer.append(this .lineSeparator);
1762:
1763:                for (int i = 0; i < (pageWidth / tabLength); i++) {
1764:                    stringBuffer.append(i);
1765:                    stringBuffer.append('\t');
1766:                }
1767:            }
1768:
1769:            public void printTrailingComment(int numberOfNewLinesToInsert) {
1770:                try {
1771:                    // if we have a space between two tokens we ensure it will be dumped in the formatted string
1772:                    int currentTokenStartPosition = this .scanner.currentPosition;
1773:                    boolean hasWhitespaces = false;
1774:                    boolean hasLineComment = false;
1775:                    while ((this .currentToken = this .scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
1776:                        switch (this .currentToken) {
1777:                        case TerminalTokens.TokenNameWHITESPACE:
1778:                            int count = 0;
1779:                            char[] whiteSpaces = this .scanner
1780:                                    .getCurrentTokenSource();
1781:                            for (int i = 0, max = whiteSpaces.length; i < max; i++) {
1782:                                switch (whiteSpaces[i]) {
1783:                                case '\r':
1784:                                    if ((i + 1) < max) {
1785:                                        if (whiteSpaces[i + 1] == '\n') {
1786:                                            i++;
1787:                                        }
1788:                                    }
1789:                                    count++;
1790:                                    break;
1791:                                case '\n':
1792:                                    count++;
1793:                                }
1794:                            }
1795:                            if (hasLineComment) {
1796:                                if (count >= 1) {
1797:                                    currentTokenStartPosition = this .scanner
1798:                                            .getCurrentTokenStartPosition();
1799:                                    this .preserveEmptyLines(
1800:                                            numberOfNewLinesToInsert,
1801:                                            currentTokenStartPosition);
1802:                                    addDeleteEdit(
1803:                                            currentTokenStartPosition,
1804:                                            this .scanner
1805:                                                    .getCurrentTokenEndPosition());
1806:                                    this .scanner.resetTo(
1807:                                            this .scanner.currentPosition,
1808:                                            this .scannerEndPosition - 1);
1809:                                    return;
1810:                                } else {
1811:                                    this .scanner.resetTo(
1812:                                            currentTokenStartPosition,
1813:                                            this .scannerEndPosition - 1);
1814:                                    return;
1815:                                }
1816:                            } else if (count > 1) {
1817:                                this 
1818:                                        .printEmptyLines(
1819:                                                numberOfNewLinesToInsert,
1820:                                                this .scanner
1821:                                                        .getCurrentTokenStartPosition());
1822:                                this .scanner.resetTo(currentTokenStartPosition,
1823:                                        this .scannerEndPosition - 1);
1824:                                return;
1825:                            } else {
1826:                                hasWhitespaces = true;
1827:                                currentTokenStartPosition = this .scanner.currentPosition;
1828:                                addDeleteEdit(this .scanner
1829:                                        .getCurrentTokenStartPosition(),
1830:                                        this .scanner
1831:                                                .getCurrentTokenEndPosition());
1832:                            }
1833:                            break;
1834:                        case TerminalTokens.TokenNameCOMMENT_LINE:
1835:                            if (hasWhitespaces) {
1836:                                space();
1837:                            }
1838:                            this .printLineComment(this .scanner
1839:                                    .getRawTokenSource());
1840:                            currentTokenStartPosition = this .scanner.currentPosition;
1841:                            hasLineComment = true;
1842:                            break;
1843:                        case TerminalTokens.TokenNameCOMMENT_BLOCK:
1844:                            if (hasWhitespaces) {
1845:                                space();
1846:                            }
1847:                            this .printBlockComment(this .scanner
1848:                                    .getRawTokenSource(), false);
1849:                            currentTokenStartPosition = this .scanner.currentPosition;
1850:                            break;
1851:                        default:
1852:                            // step back one token
1853:                            this .scanner.resetTo(currentTokenStartPosition,
1854:                                    this .scannerEndPosition - 1);
1855:                            return;
1856:                        }
1857:                    }
1858:                } catch (InvalidInputException e) {
1859:                    throw new AbortFormatting(e);
1860:                }
1861:            }
1862:
1863:            public void printTrailingComment() {
1864:                try {
1865:                    // if we have a space between two tokens we ensure it will be dumped in the formatted string
1866:                    int currentTokenStartPosition = this .scanner.currentPosition;
1867:                    boolean hasWhitespaces = false;
1868:                    boolean hasComment = false;
1869:                    boolean hasLineComment = false;
1870:                    while ((this .currentToken = this .scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
1871:                        switch (this .currentToken) {
1872:                        case TerminalTokens.TokenNameWHITESPACE:
1873:                            int count = 0;
1874:                            char[] whiteSpaces = this .scanner
1875:                                    .getCurrentTokenSource();
1876:                            for (int i = 0, max = whiteSpaces.length; i < max; i++) {
1877:                                switch (whiteSpaces[i]) {
1878:                                case '\r':
1879:                                    if ((i + 1) < max) {
1880:                                        if (whiteSpaces[i + 1] == '\n') {
1881:                                            i++;
1882:                                        }
1883:                                    }
1884:                                    count++;
1885:                                    break;
1886:                                case '\n':
1887:                                    count++;
1888:                                }
1889:                            }
1890:                            if (hasLineComment) {
1891:                                if (count >= 1) {
1892:                                    currentTokenStartPosition = this .scanner
1893:                                            .getCurrentTokenStartPosition();
1894:                                    this .preserveEmptyLines(count,
1895:                                            currentTokenStartPosition);
1896:                                    addDeleteEdit(
1897:                                            currentTokenStartPosition,
1898:                                            this .scanner
1899:                                                    .getCurrentTokenEndPosition());
1900:                                    this .scanner.resetTo(
1901:                                            this .scanner.currentPosition,
1902:                                            this .scannerEndPosition - 1);
1903:                                    return;
1904:                                } else {
1905:                                    this .scanner.resetTo(
1906:                                            currentTokenStartPosition,
1907:                                            this .scannerEndPosition - 1);
1908:                                    return;
1909:                                }
1910:                            } else if (count >= 1) {
1911:                                if (hasComment) {
1912:                                    this .printNewLine(this .scanner
1913:                                            .getCurrentTokenStartPosition());
1914:                                }
1915:                                this .scanner.resetTo(currentTokenStartPosition,
1916:                                        this .scannerEndPosition - 1);
1917:                                return;
1918:                            } else {
1919:                                hasWhitespaces = true;
1920:                                currentTokenStartPosition = this .scanner.currentPosition;
1921:                                addDeleteEdit(this .scanner
1922:                                        .getCurrentTokenStartPosition(),
1923:                                        this .scanner
1924:                                                .getCurrentTokenEndPosition());
1925:                            }
1926:                            break;
1927:                        case TerminalTokens.TokenNameCOMMENT_LINE:
1928:                            if (hasWhitespaces) {
1929:                                space();
1930:                            }
1931:                            this .printLineComment(this .scanner
1932:                                    .getRawTokenSource());
1933:                            currentTokenStartPosition = this .scanner.currentPosition;
1934:                            hasLineComment = true;
1935:                            break;
1936:                        case TerminalTokens.TokenNameCOMMENT_BLOCK:
1937:                            if (hasWhitespaces) {
1938:                                space();
1939:                            }
1940:                            this .printBlockComment(this .scanner
1941:                                    .getRawTokenSource(), false);
1942:                            currentTokenStartPosition = this .scanner.currentPosition;
1943:                            hasComment = true;
1944:                            break;
1945:                        default:
1946:                            // step back one token
1947:                            this .scanner.resetTo(currentTokenStartPosition,
1948:                                    this .scannerEndPosition - 1);
1949:                            return;
1950:                        }
1951:                    }
1952:                } catch (InvalidInputException e) {
1953:                    throw new AbortFormatting(e);
1954:                }
1955:            }
1956:
1957:            void redoAlignment(AlignmentException e) {
1958:                if (e.relativeDepth > 0) { // if exception targets a distinct context
1959:                    e.relativeDepth--; // record fact that current context got traversed
1960:                    this .currentAlignment = this .currentAlignment.enclosing; // pop currentLocation
1961:                    throw e; // rethrow
1962:                }
1963:                // reset scribe/scanner to restart at this given location
1964:                this .resetAt(this .currentAlignment.location);
1965:                this .scanner.resetTo(
1966:                        this .currentAlignment.location.inputOffset,
1967:                        this .scanner.eofPosition);
1968:                // clean alignment chunkKind so it will think it is a new chunk again
1969:                this .currentAlignment.chunkKind = 0;
1970:            }
1971:
1972:            void redoMemberAlignment(AlignmentException e) {
1973:                // reset scribe/scanner to restart at this given location
1974:                this .resetAt(this .memberAlignment.location);
1975:                this .scanner.resetTo(this .memberAlignment.location.inputOffset,
1976:                        this .scanner.eofPosition);
1977:                // clean alignment chunkKind so it will think it is a new chunk again
1978:                this .memberAlignment.chunkKind = 0;
1979:            }
1980:
1981:            public void reset() {
1982:                this .checkLineWrapping = true;
1983:                this .line = 0;
1984:                this .column = 1;
1985:                this .editsIndex = 0;
1986:                this .nlsTagCounter = 0;
1987:            }
1988:
1989:            private void resetAt(Location location) {
1990:                this .line = location.outputLine;
1991:                this .column = location.outputColumn;
1992:                this .indentationLevel = location.outputIndentationLevel;
1993:                this .numberOfIndentations = location.numberOfIndentations;
1994:                this .lastNumberOfNewLines = location.lastNumberOfNewLines;
1995:                this .needSpace = location.needSpace;
1996:                this .pendingSpace = location.pendingSpace;
1997:                this .editsIndex = location.editsIndex;
1998:                this .nlsTagCounter = location.nlsTagCounter;
1999:                if (this .editsIndex > 0) {
2000:                    this .edits[this .editsIndex - 1] = location.textEdit;
2001:                }
2002:                this .formatter.lastLocalDeclarationSourceStart = location.lastLocalDeclarationSourceStart;
2003:            }
2004:
2005:            private void resize() {
2006:                System
2007:                        .arraycopy(
2008:                                this .edits,
2009:                                0,
2010:                                (this .edits = new OptimizedReplaceEdit[this .editsIndex * 2]),
2011:                                0, this .editsIndex);
2012:            }
2013:
2014:            public void space() {
2015:                if (!this .needSpace)
2016:                    return;
2017:                this .lastNumberOfNewLines = 0;
2018:                this .pendingSpace = true;
2019:                this .column++;
2020:                this .needSpace = false;
2021:            }
2022:
2023:            public String toString() {
2024:                StringBuffer stringBuffer = new StringBuffer();
2025:                stringBuffer
2026:                        .append("(page width = " + this .pageWidth + ") - (tabChar = ");//$NON-NLS-1$//$NON-NLS-2$
2027:                switch (this .tabChar) {
2028:                case DefaultCodeFormatterOptions.TAB:
2029:                    stringBuffer.append("TAB");//$NON-NLS-1$
2030:                    break;
2031:                case DefaultCodeFormatterOptions.SPACE:
2032:                    stringBuffer.append("SPACE");//$NON-NLS-1$
2033:                    break;
2034:                default:
2035:                    stringBuffer.append("MIXED");//$NON-NLS-1$
2036:                }
2037:                stringBuffer
2038:                        .append(") - (tabSize = " + this .tabLength + ")")//$NON-NLS-1$//$NON-NLS-2$
2039:                        .append(this .lineSeparator)
2040:                        .append(
2041:                                "(line = " + this .line + ") - (column = " + this .column + ") - (identationLevel = " + this .indentationLevel + ")") //$NON-NLS-1$	//$NON-NLS-2$	//$NON-NLS-3$	//$NON-NLS-4$
2042:                        .append(this .lineSeparator)
2043:                        .append(
2044:                                "(needSpace = " + this .needSpace + ") - (lastNumberOfNewLines = " + this .lastNumberOfNewLines + ") - (checkLineWrapping = " + this .checkLineWrapping + ")") //$NON-NLS-1$	//$NON-NLS-2$	//$NON-NLS-3$	//$NON-NLS-4$
2045:                        .append(this .lineSeparator)
2046:                        .append(
2047:                                "==================================================================================") //$NON-NLS-1$
2048:                        .append(this .lineSeparator);
2049:                printRule(stringBuffer);
2050:                return stringBuffer.toString();
2051:            }
2052:
2053:            public void unIndent() {
2054:                this.indentationLevel -= this.indentationSize;
2055:                this.numberOfIndentations--;
2056:            }
2057:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.