KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > formatter > CodeFormatterVisitor2


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

11 package org.eclipse.jdt.internal.formatter;
12
13 import java.util.List JavaDoc;
14 import java.util.Map JavaDoc;
15
16 import org.eclipse.jdt.core.JavaCore;
17 import org.eclipse.jdt.core.compiler.InvalidInputException;
18 import org.eclipse.jdt.core.dom.*;
19 import org.eclipse.jdt.core.dom.PrefixExpression.Operator;
20 import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants;
21 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
22 import org.eclipse.jdt.internal.compiler.parser.Scanner;
23 import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
24 import org.eclipse.jdt.internal.formatter.align.Alignment;
25 import org.eclipse.jdt.internal.formatter.align.Alignment2;
26 import org.eclipse.jdt.internal.formatter.align.AlignmentException;
27 import org.eclipse.text.edits.TextEdit;
28
29 /**
30  * This class is responsible for formatting a valid java source code.
31  * @since 3.2
32  */

33 public class CodeFormatterVisitor2 extends ASTVisitor {
34     public static boolean DEBUG = false;
35     
36     private static final int[] CLOSING_GENERICS_EXPECTEDTOKENS = new int[] {
37         TerminalTokens.TokenNameRIGHT_SHIFT,
38         TerminalTokens.TokenNameUNSIGNED_RIGHT_SHIFT,
39         TerminalTokens.TokenNameGREATER
40     };
41     private static final int[] NUMBER_LITERALS_EXPECTEDTOKENS = new int[] {
42         TerminalTokens.TokenNameIntegerLiteral,
43         TerminalTokens.TokenNameLongLiteral,
44         TerminalTokens.TokenNameFloatingPointLiteral,
45         TerminalTokens.TokenNameDoubleLiteral
46     };
47     /*
48      * Set of expected tokens type for a single type reference.
49      * This array needs to be SORTED.
50      */

51     private static final int[] PRIMITIVE_TYPE_EXPECTEDTOKENS = new int[] {
52         TerminalTokens.TokenNameboolean,
53         TerminalTokens.TokenNamebyte,
54         TerminalTokens.TokenNamechar,
55         TerminalTokens.TokenNamedouble,
56         TerminalTokens.TokenNamefloat,
57         TerminalTokens.TokenNameint,
58         TerminalTokens.TokenNamelong,
59         TerminalTokens.TokenNameshort,
60         TerminalTokens.TokenNamevoid
61     };
62     private Scanner localScanner;
63
64     public DefaultCodeFormatterOptions preferences;
65     
66     public Scribe2 scribe;
67
68     public CodeFormatterVisitor2(DefaultCodeFormatterOptions preferences, Map JavaDoc settings, int offset, int length, CompilationUnit unit) {
69         if (settings != null) {
70             Object JavaDoc assertModeSetting = settings.get(JavaCore.COMPILER_SOURCE);
71             long sourceLevel = ClassFileConstants.JDK1_3;
72             if (JavaCore.VERSION_1_4.equals(assertModeSetting)) {
73                 sourceLevel = ClassFileConstants.JDK1_4;
74             } else if (JavaCore.VERSION_1_5.equals(assertModeSetting)) {
75                 sourceLevel = ClassFileConstants.JDK1_5;
76             }
77             this.localScanner = new Scanner(true, false, false/*nls*/, sourceLevel/*sourceLevel*/, null/*taskTags*/, null/*taskPriorities*/, true/*taskCaseSensitive*/);
78         } else {
79             this.localScanner = new Scanner(true, false, false/*nls*/, ClassFileConstants.JDK1_3/*sourceLevel*/, null/*taskTags*/, null/*taskPriorities*/, true/*taskCaseSensitive*/);
80         }
81         
82         this.preferences = preferences;
83         this.scribe = new Scribe2(this, settings, offset, length, unit);
84     }
85
86     private boolean commentStartsBlock(int start, int end) {
87         this.localScanner.resetTo(start, end);
88         try {
89             if (this.localScanner.getNextToken() == TerminalTokens.TokenNameLBRACE) {
90                 switch(this.localScanner.getNextToken()) {
91                     case TerminalTokens.TokenNameCOMMENT_BLOCK :
92                     case TerminalTokens.TokenNameCOMMENT_JAVADOC :
93                     case TerminalTokens.TokenNameCOMMENT_LINE :
94                         return true;
95                 }
96             }
97         } catch(InvalidInputException e) {
98             // ignore
99
}
100         return false;
101     }
102     
103
104     public static int extractInfixExpressionOperator(InfixExpression node) {
105         final InfixExpression.Operator infixOperator = node.getOperator();
106         if (infixOperator == InfixExpression.Operator.AND) {
107             return TerminalTokens.TokenNameAND;
108         } else if (infixOperator == InfixExpression.Operator.CONDITIONAL_AND) {
109             return TerminalTokens.TokenNameAND_AND;
110         } else if (infixOperator == InfixExpression.Operator.CONDITIONAL_OR) {
111             return TerminalTokens.TokenNameOR_OR;
112         } else if (infixOperator == InfixExpression.Operator.DIVIDE) {
113             return TerminalTokens.TokenNameDIVIDE;
114         } else if (infixOperator == InfixExpression.Operator.EQUALS) {
115             return TerminalTokens.TokenNameEQUAL_EQUAL;
116         } else if (infixOperator == InfixExpression.Operator.GREATER) {
117             return TerminalTokens.TokenNameGREATER;
118         } else if (infixOperator == InfixExpression.Operator.GREATER_EQUALS) {
119             return TerminalTokens.TokenNameGREATER_EQUAL;
120         } else if (infixOperator == InfixExpression.Operator.LEFT_SHIFT) {
121             return TerminalTokens.TokenNameLEFT_SHIFT;
122         } else if (infixOperator == InfixExpression.Operator.LESS) {
123             return TerminalTokens.TokenNameLESS;
124         } else if (infixOperator == InfixExpression.Operator.LESS_EQUALS) {
125             return TerminalTokens.TokenNameLESS_EQUAL;
126         } else if (infixOperator == InfixExpression.Operator.MINUS) {
127             return TerminalTokens.TokenNameMINUS;
128         } else if (infixOperator == InfixExpression.Operator.NOT_EQUALS) {
129             return TerminalTokens.TokenNameNOT_EQUAL;
130         } else if (infixOperator == InfixExpression.Operator.OR) {
131             return TerminalTokens.TokenNameOR;
132         } else if (infixOperator == InfixExpression.Operator.PLUS) {
133             return TerminalTokens.TokenNamePLUS;
134         } else if (infixOperator == InfixExpression.Operator.REMAINDER) {
135             return TerminalTokens.TokenNameREMAINDER;
136         } else if (infixOperator == InfixExpression.Operator.RIGHT_SHIFT_SIGNED) {
137             return TerminalTokens.TokenNameRIGHT_SHIFT;
138         } else if (infixOperator == InfixExpression.Operator.RIGHT_SHIFT_UNSIGNED) {
139             return TerminalTokens.TokenNameUNSIGNED_RIGHT_SHIFT;
140         } else if (infixOperator == InfixExpression.Operator.TIMES) {
141             return TerminalTokens.TokenNameMULTIPLY;
142         } else {
143             return TerminalTokens.TokenNameXOR;
144         }
145     }
146
147     private final TextEdit failedToFormat() {
148         if (DEBUG) {
149             System.out.println("COULD NOT FORMAT \n" + this.scribe.scanner); //$NON-NLS-1$
150
System.out.println(this.scribe);
151         }
152         return null;
153     }
154
155     /**
156      * @see org.eclipse.jdt.core.formatter.CodeFormatter#format(int, String, int, int, int, String)
157      */

158     public TextEdit format(String JavaDoc string, AbstractTypeDeclaration typeDeclaration) {
159         // reset the scribe
160
this.scribe.reset();
161         
162         long startTime = System.currentTimeMillis();
163     
164         final char[] compilationUnitSource = string.toCharArray();
165         
166         this.localScanner.setSource(compilationUnitSource);
167         this.scribe.initializeScanner(compilationUnitSource);
168     
169         try {
170             this.scribe.lastNumberOfNewLines = 1;
171             formatTypeMembers(typeDeclaration.bodyDeclarations(), false);
172         } catch(AbortFormatting e){
173             return failedToFormat();
174         }
175         if (DEBUG){
176             System.out.println("Formatting time: " + (System.currentTimeMillis() - startTime)); //$NON-NLS-1$
177
}
178         return this.scribe.getRootEdit();
179     }
180
181     /**
182      * @see org.eclipse.jdt.core.formatter.CodeFormatter#format(int, String, int, int, int, String)
183      */

184     public TextEdit format(String JavaDoc string, Block block) {
185         // reset the scribe
186
this.scribe.reset();
187         
188         long startTime = System.currentTimeMillis();
189
190         final char[] compilationUnitSource = string.toCharArray();
191         
192         this.localScanner.setSource(compilationUnitSource);
193         this.scribe.initializeScanner(compilationUnitSource);
194
195         if ((block.getFlags() & ASTNode.MALFORMED) != 0) {
196             return failedToFormat();
197         }
198
199         try {
200             formatStatements(block.statements(), false);
201             if (hasComments()) {
202                 this.scribe.printNewLine();
203             }
204             this.scribe.printComment();
205         } catch(AbortFormatting e){
206             return failedToFormat();
207         }
208         if (DEBUG){
209             System.out.println("Formatting time: " + (System.currentTimeMillis() - startTime)); //$NON-NLS-1$
210
}
211         return this.scribe.getRootEdit();
212     }
213
214     /**
215      * @see org.eclipse.jdt.core.formatter.CodeFormatter#format(int, String, int, int, int, String)
216      */

217     public TextEdit format(String JavaDoc string, CompilationUnit compilationUnit) {
218         // reset the scribe
219
this.scribe.reset();
220         
221         if ((compilationUnit.getFlags() & ASTNode.MALFORMED) != 0) {
222             return failedToFormat();
223         }
224
225         long startTime = System.currentTimeMillis();
226
227         final char[] compilationUnitSource = string.toCharArray();
228         
229         this.localScanner.setSource(compilationUnitSource);
230         this.scribe.initializeScanner(compilationUnitSource);
231
232         try {
233             compilationUnit.accept(this);
234         } catch(AbortFormatting e){
235             return failedToFormat();
236         }
237         if (DEBUG){
238             System.out.println("Formatting time: " + (System.currentTimeMillis() - startTime)); //$NON-NLS-1$
239
}
240         return this.scribe.getRootEdit();
241     }
242
243     /**
244      * @see org.eclipse.jdt.core.formatter.CodeFormatter#format(int, String, int, int, int, String)
245      */

246     public TextEdit format(String JavaDoc string, Expression expression) {
247         // reset the scribe
248
this.scribe.reset();
249         
250         long startTime = System.currentTimeMillis();
251
252         final char[] compilationUnitSource = string.toCharArray();
253         
254         this.localScanner.setSource(compilationUnitSource);
255         this.scribe.initializeScanner(compilationUnitSource);
256
257         if ((expression.getFlags() & ASTNode.MALFORMED) != 0) {
258             return failedToFormat();
259         }
260         try {
261             expression.accept(this);
262             this.scribe.printComment();
263         } catch(AbortFormatting e){
264             return failedToFormat();
265         }
266         if (DEBUG){
267             System.out.println("Formatting time: " + (System.currentTimeMillis() - startTime)); //$NON-NLS-1$
268
}
269         return this.scribe.getRootEdit();
270     }
271
272     private void format(
273             AbstractTypeDeclaration memberTypeDeclaration,
274             boolean isChunkStart,
275             boolean isFirstClassBodyDeclaration) {
276
277             if (isFirstClassBodyDeclaration) {
278                 int newLinesBeforeFirstClassBodyDeclaration = this.preferences.blank_lines_before_first_class_body_declaration;
279                 if (newLinesBeforeFirstClassBodyDeclaration > 0) {
280                     this.scribe.printEmptyLines(newLinesBeforeFirstClassBodyDeclaration);
281                 }
282             } else {
283                 int newLineBeforeChunk = isChunkStart ? this.preferences.blank_lines_before_new_chunk : 0;
284                 if (newLineBeforeChunk > 0) {
285                     this.scribe.printEmptyLines(newLineBeforeChunk);
286                 }
287                 final int newLinesBeforeMember = this.preferences.blank_lines_before_member_type;
288                 if (newLinesBeforeMember > 0) {
289                     this.scribe.printEmptyLines(newLinesBeforeMember);
290                 }
291             }
292             memberTypeDeclaration.accept(this);
293         }
294
295     private void format(FieldDeclaration fieldDeclaration, boolean isChunkStart, boolean isFirstClassBodyDeclaration) {
296         if (isFirstClassBodyDeclaration) {
297             int newLinesBeforeFirstClassBodyDeclaration = this.preferences.blank_lines_before_first_class_body_declaration;
298             if (newLinesBeforeFirstClassBodyDeclaration > 0) {
299                 this.scribe.printEmptyLines(newLinesBeforeFirstClassBodyDeclaration);
300             }
301         } else {
302             int newLineBeforeChunk = isChunkStart ? this.preferences.blank_lines_before_new_chunk : 0;
303             if (newLineBeforeChunk > 0) {
304                 this.scribe.printEmptyLines(newLineBeforeChunk);
305             }
306             final int newLinesBeforeField = this.preferences.blank_lines_before_field;
307             if (newLinesBeforeField > 0) {
308                 this.scribe.printEmptyLines(newLinesBeforeField);
309             }
310         }
311         Alignment2 memberAlignment = this.scribe.getMemberAlignment();
312     
313         this.scribe.printComment();
314         final List JavaDoc modifiers = fieldDeclaration.modifiers();
315         if (modifiers.size() != 0) {
316             this.scribe.printModifiers(modifiers, this);
317             this.scribe.space();
318         }
319
320         fieldDeclaration.getType().accept(this);
321         
322         List JavaDoc fragments = fieldDeclaration.fragments();
323         final int fragmentsLength = fragments.size();
324         if (fragmentsLength > 1) {
325             // multiple field declaration
326
Alignment2 multiFieldDeclarationsAlignment =this.scribe.createAlignment(
327                     "multiple_field",//$NON-NLS-1$
328
this.preferences.alignment_for_multiple_fields,
329                     fragmentsLength - 1,
330                     this.scribe.scanner.currentPosition);
331             this.scribe.enterAlignment(multiFieldDeclarationsAlignment);
332         
333             boolean ok = false;
334             do {
335                 try {
336                     for (int i = 0; i < fragmentsLength; i++) {
337                         VariableDeclarationFragment fragment = (VariableDeclarationFragment) fragments.get(i);
338                         /*
339                          * Field name
340                          */

341                         if (i == 0) {
342                             this.scribe.alignFragment(memberAlignment, 0);
343                             this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, true);
344                         } else {
345                             this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, false);
346                         }
347                 
348                         /*
349                          * Check for extra dimensions
350                          */

351                         final int extraDimensions = fragment.getExtraDimensions();
352                         if (extraDimensions != 0) {
353                              for (int index = 0; index < extraDimensions; index++) {
354                                 this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET);
355                                 this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET);
356                              }
357                         }
358                     
359                         /*
360                          * Field initialization
361                          */

362                         final Expression initialization = fragment.getInitializer();
363                         if (initialization != null) {
364                             if (i == 0) {
365                                 this.scribe.alignFragment(memberAlignment, 1);
366                             }
367                             this.scribe.printNextToken(TerminalTokens.TokenNameEQUAL, this.preferences.insert_space_before_assignment_operator);
368                             if (this.preferences.insert_space_after_assignment_operator) {
369                                 this.scribe.space();
370                             }
371                             Alignment2 assignmentAlignment = this.scribe.createAlignment("fieldDeclarationAssignmentAlignment", this.preferences.alignment_for_assignment, 1, this.scribe.scanner.currentPosition); //$NON-NLS-1$
372
this.scribe.enterAlignment(assignmentAlignment);
373                             boolean ok2 = false;
374                             do {
375                                 try {
376                                     this.scribe.alignFragment(assignmentAlignment, 0);
377                                     initialization.accept(this);
378                                     ok2 = true;
379                                 } catch(AlignmentException e){
380                                     this.scribe.redoAlignment(e);
381                                 }
382                             } while (!ok2);
383                             this.scribe.exitAlignment(assignmentAlignment, true);
384                         }
385                         
386                         if (i != fragmentsLength - 1) {
387                             this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_multiple_field_declarations);
388                             this.scribe.printTrailingComment();
389                             this.scribe.alignFragment(multiFieldDeclarationsAlignment, i);
390
391                             if (this.preferences.insert_space_after_comma_in_multiple_field_declarations) {
392                                 this.scribe.space();
393                             }
394                         } else {
395                             this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
396                             this.scribe.alignFragment(memberAlignment, 2);
397                             this.scribe.printTrailingComment();
398                         }
399                     }
400                     ok = true;
401                 } catch (AlignmentException e) {
402                     this.scribe.redoAlignment(e);
403                 }
404             } while (!ok);
405             this.scribe.exitAlignment(multiFieldDeclarationsAlignment, true);
406         } else {
407             // single field declaration
408
this.scribe.alignFragment(memberAlignment, 0);
409             this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, true);
410             VariableDeclarationFragment fragment = (VariableDeclarationFragment) fragments.get(0);
411             final int extraDimensions = fragment.getExtraDimensions();
412             if (extraDimensions != 0) {
413                 for (int i = 0; i < extraDimensions; i++) {
414                     this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET);
415                     this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET);
416                 }
417             }
418             final Expression initialization = fragment.getInitializer();
419             if (initialization != null) {
420                 this.scribe.alignFragment(memberAlignment, 1);
421                 this.scribe.printNextToken(TerminalTokens.TokenNameEQUAL, this.preferences.insert_space_before_assignment_operator);
422                 if (this.preferences.insert_space_after_assignment_operator) {
423                     this.scribe.space();
424                 }
425                 Alignment2 assignmentAlignment = this.scribe.createAlignment("fieldDeclarationAssignmentAlignment", this.preferences.alignment_for_assignment, 1, this.scribe.scanner.currentPosition); //$NON-NLS-1$
426
this.scribe.enterAlignment(assignmentAlignment);
427                 boolean ok = false;
428                 do {
429                     try {
430                         this.scribe.alignFragment(assignmentAlignment, 0);
431                         initialization.accept(this);
432                         ok = true;
433                     } catch(AlignmentException e){
434                         this.scribe.redoAlignment(e);
435                     }
436                 } while (!ok);
437                 this.scribe.exitAlignment(assignmentAlignment, true);
438             }
439             
440             this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
441
442             if (memberAlignment != null) {
443                 this.scribe.alignFragment(memberAlignment, 2);
444                 this.scribe.printTrailingComment();
445             } else {
446                 this.scribe.space();
447                 this.scribe.printTrailingComment();
448             }
449         }
450     }
451     private void format(
452             BodyDeclaration bodyDeclaration,
453             boolean isChunkStart,
454             boolean isFirstClassBodyDeclaration) {
455
456         if (isFirstClassBodyDeclaration) {
457             int newLinesBeforeFirstClassBodyDeclaration = this.preferences.blank_lines_before_first_class_body_declaration;
458             if (newLinesBeforeFirstClassBodyDeclaration > 0) {
459                 this.scribe.printEmptyLines(newLinesBeforeFirstClassBodyDeclaration);
460             }
461         } else {
462             final int newLineBeforeChunk = isChunkStart ? this.preferences.blank_lines_before_new_chunk : 0;
463             if (newLineBeforeChunk > 0) {
464                 this.scribe.printEmptyLines(newLineBeforeChunk);
465             }
466         }
467         final int newLinesBeforeMethod = this.preferences.blank_lines_before_method;
468         if (newLinesBeforeMethod > 0 && !isFirstClassBodyDeclaration) {
469             this.scribe.printEmptyLines(newLinesBeforeMethod);
470         } else if (this.scribe.line != 0 || this.scribe.column != 1) {
471             this.scribe.printNewLine();
472         }
473         bodyDeclaration.accept(this);
474     }
475
476     private void formatAction(final int line, final Statement action, boolean insertLineForSingleStatement) {
477         if (action != null) {
478             switch(action.getNodeType()) {
479                 case ASTNode.BLOCK :
480                     formatLeftCurlyBrace(line, this.preferences.brace_position_for_block);
481                     action.accept(this);
482                     break;
483                 case ASTNode.EMPTY_STATEMENT :
484                     this.scribe.indent();
485                     action.accept(this);
486                     this.scribe.unIndent();
487                     break;
488                 default :
489                     this.scribe.printNewLine();
490                     this.scribe.indent();
491                     action.accept(this);
492                     this.scribe.unIndent();
493                     if (insertLineForSingleStatement) {
494                         this.scribe.printNewLine();
495                     }
496             }
497         } else {
498             // empty statement
499
this.scribe.indent();
500             action.accept(this);
501             this.scribe.unIndent();
502         }
503     }
504
505     private void formatBlock(Block block, String JavaDoc block_brace_position, boolean insertSpaceBeforeOpeningBrace) {
506         formatOpeningBrace(block_brace_position, insertSpaceBeforeOpeningBrace);
507         final List JavaDoc statements = block.statements();
508         final int statementsLength = statements.size();
509         if (statementsLength != 0) {
510             this.scribe.printNewLine();
511             if (this.preferences.indent_statements_compare_to_block) {
512                 this.scribe.indent();
513             }
514             formatStatements(statements, true);
515             this.scribe.printComment();
516     
517             if (this.preferences.indent_statements_compare_to_block) {
518                 this.scribe.unIndent();
519             }
520         } else {
521             if (this.preferences.insert_new_line_in_empty_block) {
522                 this.scribe.printNewLine();
523             }
524             if (this.preferences.indent_statements_compare_to_block) {
525                 this.scribe.indent();
526             }
527             this.scribe.printComment();
528     
529             if (this.preferences.indent_statements_compare_to_block) {
530                 this.scribe.unIndent();
531             }
532         }
533         this.scribe.printNextToken(TerminalTokens.TokenNameRBRACE);
534         this.scribe.printTrailingComment();
535         if (DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED.equals(block_brace_position)) {
536             this.scribe.unIndent();
537         }
538     }
539
540     private void formatEmptyTypeDeclaration(boolean isFirst) {
541         boolean hasSemiColon = isNextToken(TerminalTokens.TokenNameSEMICOLON);
542         while(isNextToken(TerminalTokens.TokenNameSEMICOLON)) {
543             this.scribe.printComment();
544             this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
545             this.scribe.printTrailingComment();
546         }
547         if (hasSemiColon && isFirst) {
548             this.scribe.printNewLine();
549         }
550     }
551
552
553     private void formatLeftCurlyBrace(final int line, final String JavaDoc bracePosition) {
554         /*
555          * deal with (quite unexpected) comments right before lcurly
556          */

557         this.scribe.printComment();
558         if (DefaultCodeFormatterConstants.NEXT_LINE_ON_WRAP.equals(bracePosition)
559                 && (this.scribe.line > line || this.scribe.column >= this.preferences.page_width))
560         {
561             this.scribe.printNewLine();
562         }
563     }
564
565     private void formatLocalDeclaration(VariableDeclarationExpression declarationExpression, boolean insertSpaceBeforeComma, boolean insertSpaceAfterComma) {
566         final List JavaDoc modifiers = declarationExpression.modifiers();
567         if (modifiers.size() != 0) {
568             this.scribe.printModifiers(modifiers, this);
569             this.scribe.space();
570         }
571
572         declarationExpression.getType().accept(this);
573         
574         formatVariableDeclarationFragments(declarationExpression.fragments(), insertSpaceBeforeComma, insertSpaceAfterComma);
575     }
576
577     private void formatVariableDeclarationFragments(final List JavaDoc fragments, boolean insertSpaceBeforeComma, boolean insertSpaceAfterComma) {
578         final int fragmentsLength = fragments.size();
579         if (fragmentsLength > 1) {
580             // multiple field declaration
581
Alignment2 multiFieldDeclarationsAlignment =this.scribe.createAlignment(
582                     "multiple_field",//$NON-NLS-1$
583
this.preferences.alignment_for_multiple_fields,
584                     fragmentsLength - 1,
585                     this.scribe.scanner.currentPosition);
586             this.scribe.enterAlignment(multiFieldDeclarationsAlignment);
587         
588             boolean ok = false;
589             do {
590                 try {
591                     for (int i = 0; i < fragmentsLength; i++) {
592                         VariableDeclarationFragment fragment = (VariableDeclarationFragment) fragments.get(i);
593                         /*
594                          * Field name
595                          */

596                         if (i == 0) {
597                             this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, true);
598                         } else {
599                             this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, false);
600                         }
601                 
602                         /*
603                          * Check for extra dimensions
604                          */

605                         final int extraDimensions = fragment.getExtraDimensions();
606                         if (extraDimensions != 0) {
607                              for (int index = 0; index < extraDimensions; index++) {
608                                 this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET);
609                                 this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET);
610                              }
611                         }
612                     
613                         /*
614                          * Field initialization
615                          */

616                         final Expression initialization = fragment.getInitializer();
617                         if (initialization != null) {
618                             this.scribe.printNextToken(TerminalTokens.TokenNameEQUAL, this.preferences.insert_space_before_assignment_operator);
619                             if (this.preferences.insert_space_after_assignment_operator) {
620                                 this.scribe.space();
621                             }
622                             Alignment2 assignmentAlignment = this.scribe.createAlignment("fieldDeclarationAssignmentAlignment", this.preferences.alignment_for_assignment, 1, this.scribe.scanner.currentPosition); //$NON-NLS-1$
623
this.scribe.enterAlignment(assignmentAlignment);
624                             boolean ok2 = false;
625                             do {
626                                 try {
627                                     this.scribe.alignFragment(assignmentAlignment, 0);
628                                     initialization.accept(this);
629                                     ok2 = true;
630                                 } catch(AlignmentException e){
631                                     this.scribe.redoAlignment(e);
632                                 }
633                             } while (!ok2);
634                             this.scribe.exitAlignment(assignmentAlignment, true);
635                         }
636                         
637                         if (i != fragmentsLength - 1) {
638                             this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, insertSpaceBeforeComma);
639                             this.scribe.printTrailingComment();
640                             this.scribe.alignFragment(multiFieldDeclarationsAlignment, i);
641
642                             if (insertSpaceAfterComma) {
643                                 this.scribe.space();
644                             }
645                         }
646                     }
647                     ok = true;
648                 } catch (AlignmentException e) {
649                     this.scribe.redoAlignment(e);
650                 }
651             } while (!ok);
652             this.scribe.exitAlignment(multiFieldDeclarationsAlignment, true);
653         } else {
654             // single field declaration
655
this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, true);
656             VariableDeclarationFragment fragment = (VariableDeclarationFragment) fragments.get(0);
657             final int extraDimensions = fragment.getExtraDimensions();
658             if (extraDimensions != 0) {
659                 for (int i = 0; i < extraDimensions; i++) {
660                     this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET);
661                     this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET);
662                 }
663             }
664             final Expression initialization = fragment.getInitializer();
665             if (initialization != null) {
666                 this.scribe.printNextToken(TerminalTokens.TokenNameEQUAL, this.preferences.insert_space_before_assignment_operator);
667                 if (this.preferences.insert_space_after_assignment_operator) {
668                     this.scribe.space();
669                 }
670                 Alignment2 assignmentAlignment = this.scribe.createAlignment("localDeclarationAssignmentAlignment", this.preferences.alignment_for_assignment, 1, this.scribe.scanner.currentPosition); //$NON-NLS-1$
671
this.scribe.enterAlignment(assignmentAlignment);
672                 boolean ok = false;
673                 do {
674                     try {
675                         this.scribe.alignFragment(assignmentAlignment, 0);
676                         initialization.accept(this);
677                         ok = true;
678                     } catch(AlignmentException e){
679                         this.scribe.redoAlignment(e);
680                     }
681                 } while (!ok);
682                 this.scribe.exitAlignment(assignmentAlignment, true);
683             }
684         }
685     }
686
687     private void formatOpeningBrace(String JavaDoc bracePosition, boolean insertSpaceBeforeBrace) {
688         if (DefaultCodeFormatterConstants.NEXT_LINE.equals(bracePosition)) {
689             this.scribe.printNewLine();
690         } else if (DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED.equals(bracePosition)) {
691             this.scribe.printNewLine();
692             this.scribe.indent();
693         }
694         this.scribe.printNextToken(TerminalTokens.TokenNameLBRACE, insertSpaceBeforeBrace);
695
696         this.scribe.printTrailingComment();
697     }
698     
699     private void formatStatements(final List JavaDoc statements, boolean insertNewLineAfterLastStatement) {
700         final int statementsLength = statements.size();
701         if (statementsLength > 1) {
702             Statement previousStatement = (Statement) statements.get(0);
703             previousStatement.accept(this);
704             final int previousStatementNodeType = previousStatement.getNodeType();
705             for (int i = 1; i < statementsLength - 1; i++) {
706                 final Statement statement = (Statement) statements.get(i);
707                 final int statementNodeType = statement.getNodeType();
708                 if ((previousStatementNodeType == ASTNode.EMPTY_STATEMENT
709                         && statementNodeType != ASTNode.EMPTY_STATEMENT)
710                     || (previousStatementNodeType != ASTNode.EMPTY_STATEMENT
711                         && statementNodeType != ASTNode.EMPTY_STATEMENT)) {
712                     this.scribe.printNewLine();
713                 }
714                 statement.accept(this);
715                 previousStatement = statement;
716             }
717             final Statement statement = ((Statement) statements.get(statementsLength - 1));
718             final int statementNodeType = statement.getNodeType();
719             if ((previousStatementNodeType == ASTNode.EMPTY_STATEMENT
720                     && statementNodeType != ASTNode.EMPTY_STATEMENT)
721                 || (previousStatementNodeType != ASTNode.EMPTY_STATEMENT
722                     && statementNodeType != ASTNode.EMPTY_STATEMENT)) {
723                 this.scribe.printNewLine();
724             }
725             statement.accept(this);
726         } else {
727             ((Statement) statements.get(0)).accept(this);
728         }
729         if (insertNewLineAfterLastStatement) {
730             this.scribe.printNewLine();
731         }
732     }
733
734     private void formatTypeMembers(List JavaDoc bodyDeclarations, boolean insertLineAfterLastMember) {
735         Alignment2 memberAlignment = this.scribe.createMemberAlignment("typeMembers", this.preferences.align_type_members_on_columns ? Alignment.M_MULTICOLUMN : Alignment.M_NO_ALIGNMENT, 3, this.scribe.scanner.currentPosition); //$NON-NLS-1$
736
this.scribe.enterMemberAlignment(memberAlignment);
737         boolean isChunkStart = false;
738         boolean ok = false;
739         int startIndex = 0;
740         do {
741             try {
742                 for (int i = startIndex, max = bodyDeclarations.size(); i < max; i++) {
743                     BodyDeclaration bodyDeclaration = (BodyDeclaration) bodyDeclarations.get(i);
744                     switch(bodyDeclaration.getNodeType()) {
745                         case ASTNode.FIELD_DECLARATION :
746                             isChunkStart = memberAlignment.checkChunkStart(Alignment.CHUNK_FIELD, i, this.scribe.scanner.currentPosition);
747                             FieldDeclaration fieldDeclaration = (FieldDeclaration) bodyDeclaration;
748                             format(fieldDeclaration, isChunkStart, i == 0);
749                             break;
750                         case ASTNode.INITIALIZER :
751                             isChunkStart = memberAlignment.checkChunkStart(Alignment.CHUNK_FIELD, i, this.scribe.scanner.currentPosition);
752                             int newLineBeforeChunk = isChunkStart ? this.preferences.blank_lines_before_new_chunk : 0;
753                             if (newLineBeforeChunk > 0 && i != 0) {
754                                 this.scribe.printEmptyLines(newLineBeforeChunk);
755                             } else if (i == 0) {
756                                 int newLinesBeforeFirstClassBodyDeclaration = this.preferences.blank_lines_before_first_class_body_declaration;
757                                 if (newLinesBeforeFirstClassBodyDeclaration > 0) {
758                                     this.scribe.printEmptyLines(newLinesBeforeFirstClassBodyDeclaration);
759                                 }
760                             }
761                             bodyDeclaration.accept(this);
762                             break;
763                         case ASTNode.ANNOTATION_TYPE_MEMBER_DECLARATION :
764                         case ASTNode.METHOD_DECLARATION :
765                             isChunkStart = memberAlignment.checkChunkStart(Alignment.CHUNK_METHOD, i, this.scribe.scanner.currentPosition);
766                             format(bodyDeclaration, isChunkStart, i == 0);
767                             break;
768                         case ASTNode.TYPE_DECLARATION :
769                         case ASTNode.ENUM_DECLARATION :
770                         case ASTNode.ANNOTATION_TYPE_DECLARATION :
771                             isChunkStart = memberAlignment.checkChunkStart(Alignment.CHUNK_TYPE, i, this.scribe.scanner.currentPosition);
772                             format((AbstractTypeDeclaration)bodyDeclaration, isChunkStart, i == 0);
773                     }
774                     if (isNextToken(TerminalTokens.TokenNameSEMICOLON)) {
775                         this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
776                         this.scribe.printTrailingComment();
777                     }
778                     if (i < max - 1 || insertLineAfterLastMember) {
779                         this.scribe.printNewLine();
780                     }
781                     // realign to the proper value
782
if (this.scribe.memberAlignment != null) {
783                         // select the last alignment
784
this.scribe.indentationLevel = this.scribe.memberAlignment.originalIndentationLevel;
785                     }
786                 }
787                 ok = true;
788             } catch(AlignmentException e){
789                 startIndex = memberAlignment.chunkStartIndex;
790                 this.scribe.redoMemberAlignment(e);
791             }
792         } while (!ok);
793         this.scribe.printComment();
794         this.scribe.exitMemberAlignment(memberAlignment);
795     }
796
797     private void formatTypeOpeningBrace(String JavaDoc bracePosition, boolean insertSpaceBeforeBrace, boolean insertNewLine, ASTNode node) {
798         formatOpeningBrace(bracePosition, insertSpaceBeforeBrace);
799         if (!insertNewLine) {
800             switch(node.getNodeType()) {
801                 case ASTNode.ENUM_DECLARATION :
802                     insertNewLine = this.preferences.insert_new_line_in_empty_enum_declaration;
803                     break;
804                 case ASTNode.ENUM_CONSTANT_DECLARATION :
805                     insertNewLine = this.preferences.insert_new_line_in_empty_enum_constant;
806                     break;
807                 case ASTNode.ANONYMOUS_CLASS_DECLARATION :
808                     insertNewLine = this.preferences.insert_new_line_in_empty_anonymous_type_declaration;
809                     break;
810                 case ASTNode.ANNOTATION_TYPE_DECLARATION :
811                     insertNewLine = this.preferences.insert_new_line_in_empty_annotation_declaration;
812                     break;
813                 default:
814                     insertNewLine = this.preferences.insert_new_line_in_empty_type_declaration;
815             }
816         }
817         if (insertNewLine) {
818             this.scribe.printNewLine();
819         }
820     }
821
822
823     private boolean hasComments() {
824
825         this.localScanner.resetTo(this.scribe.scanner.startPosition, this.scribe.scannerEndPosition - 1);
826         try {
827             switch(this.localScanner.getNextToken()) {
828                 case TerminalTokens.TokenNameCOMMENT_BLOCK :
829                 case TerminalTokens.TokenNameCOMMENT_JAVADOC :
830                 case TerminalTokens.TokenNameCOMMENT_LINE :
831                     return true;
832             }
833         } catch(InvalidInputException e) {
834             // ignore
835
}
836         return false;
837     }
838     
839     private boolean isClosingGenericToken() {
840         this.localScanner.resetTo(this.scribe.scanner.currentPosition, this.scribe.scannerEndPosition - 1);
841         try {
842             int token = this.localScanner.getNextToken();
843             loop: while(true) {
844                 switch(token) {
845                     case TerminalTokens.TokenNameCOMMENT_BLOCK :
846                     case TerminalTokens.TokenNameCOMMENT_JAVADOC :
847                     case TerminalTokens.TokenNameCOMMENT_LINE :
848                         token = this.localScanner.getNextToken();
849                         continue loop;
850                     default:
851                         break loop;
852                 }
853             }
854             switch(token) {
855                 case TerminalTokens.TokenNameGREATER :
856                 case TerminalTokens.TokenNameRIGHT_SHIFT :
857                 case TerminalTokens.TokenNameUNSIGNED_RIGHT_SHIFT :
858                     return true;
859             }
860         } catch(InvalidInputException e) {
861             // ignore
862
}
863         return false;
864     }
865
866     private boolean isGuardClause(Block block, List JavaDoc statements) {
867         if (commentStartsBlock(block.getStartPosition(), block.getStartPosition() + block.getLength() - 1)) return false;
868         final int statementsLength = statements.size();
869         if (statementsLength != 1) return false;
870         switch(((Statement) statements.get(0)).getNodeType()) {
871             case ASTNode.RETURN_STATEMENT :
872             case ASTNode.THROW_STATEMENT :
873                 return true;
874         }
875         return false;
876     }
877
878     private boolean isNextToken(int tokenName) {
879         this.localScanner.resetTo(this.scribe.scanner.currentPosition, this.scribe.scannerEndPosition - 1);
880         try {
881             int token = this.localScanner.getNextToken();
882             loop: while(true) {
883                 switch(token) {
884                     case TerminalTokens.TokenNameCOMMENT_BLOCK :
885                     case TerminalTokens.TokenNameCOMMENT_JAVADOC :
886                     case TerminalTokens.TokenNameCOMMENT_LINE :
887                         token = this.localScanner.getNextToken();
888                         continue loop;
889                     default:
890                         break loop;
891                 }
892             }
893             return token == tokenName;
894         } catch(InvalidInputException e) {
895             // ignore
896
}
897         return false;
898     }
899
900     public boolean visit(AnnotationTypeDeclaration node) {
901         this.scribe.printComment();
902         final int line = this.scribe.line;
903         
904         final List JavaDoc modifiers = node.modifiers();
905         if (modifiers.size() != 0) {
906             this.scribe.printModifiers(modifiers, this);
907             this.scribe.space();
908         }
909         this.scribe.printNextToken(TerminalTokens.TokenNameAT, this.preferences.insert_space_before_at_in_annotation_type_declaration);
910         this.scribe.printNextToken(TerminalTokens.TokenNameinterface, this.preferences.insert_space_after_at_in_annotation_type_declaration);
911         this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, true);
912
913         String JavaDoc class_declaration_brace;
914         boolean space_before_opening_brace;
915         class_declaration_brace = this.preferences.brace_position_for_annotation_type_declaration;
916         space_before_opening_brace = this.preferences.insert_space_before_opening_brace_in_annotation_type_declaration;
917
918         formatLeftCurlyBrace(line, class_declaration_brace);
919         final List JavaDoc bodyDeclarations = node.bodyDeclarations();
920         formatTypeOpeningBrace(class_declaration_brace, space_before_opening_brace, bodyDeclarations.size() != 0, node);
921         
922         boolean indent_body_declarations_compare_to_header = this.preferences.indent_body_declarations_compare_to_annotation_declaration_header;
923         if (indent_body_declarations_compare_to_header) {
924             this.scribe.indent();
925         }
926         
927         formatTypeMembers(bodyDeclarations, true);
928         
929         if (indent_body_declarations_compare_to_header) {
930             this.scribe.unIndent();
931         }
932         
933         if (this.preferences.insert_new_line_in_empty_annotation_declaration) {
934             this.scribe.printNewLine();
935         }
936         this.scribe.printNextToken(TerminalTokens.TokenNameRBRACE);
937         this.scribe.printTrailingComment();
938         if (class_declaration_brace.equals(DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED)) {
939             this.scribe.unIndent();
940         }
941         if (hasComments()) {
942             this.scribe.printNewLine();
943         }
944         return false;
945     }
946
947     public boolean visit(AnnotationTypeMemberDeclaration node) {
948         /*
949          * Print comments to get proper line number
950          */

951         this.scribe.printComment();
952         List JavaDoc modifiers = node.modifiers();
953         if (modifiers.size() != 0) {
954             this.scribe.printModifiers(modifiers, this);
955             this.scribe.space();
956         }
957         /*
958          * Print the method return type
959          */

960         node.getType().accept(this);
961         /*
962          * Print the method name
963          */

964         this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, true);
965         this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_annotation_type_member_declaration);
966         this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_between_empty_parens_in_annotation_type_member_declaration);
967
968         Expression defaultValue = node.getDefault();
969         if (defaultValue != null) {
970             this.scribe.printNextToken(TerminalTokens.TokenNamedefault, true);
971             this.scribe.space();
972             defaultValue.accept(this);
973         }
974         this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
975         this.scribe.printTrailingComment();
976         return false;
977     }
978
979     public boolean visit(AnonymousClassDeclaration node) {
980         /*
981          * Type body
982          */

983         String JavaDoc anonymous_type_declaration_brace_position = this.preferences.brace_position_for_anonymous_type_declaration;
984         
985         final List JavaDoc bodyDeclarations = node.bodyDeclarations();
986         formatTypeOpeningBrace(anonymous_type_declaration_brace_position, this.preferences.insert_space_before_opening_brace_in_anonymous_type_declaration, bodyDeclarations.size() != 0, node);
987         
988         this.scribe.indent();
989
990         formatTypeMembers(bodyDeclarations, true);
991
992         this.scribe.unIndent();
993         if (this.preferences.insert_new_line_in_empty_anonymous_type_declaration) {
994             this.scribe.printNewLine();
995         }
996         this.scribe.printNextToken(TerminalTokens.TokenNameRBRACE);
997         if (anonymous_type_declaration_brace_position.equals(DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED)) {
998             this.scribe.unIndent();
999         }
1000        return false;
1001    }
1002
1003    public boolean visit(ArrayAccess node) {
1004        node.getArray().accept(this);
1005        this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET, this.preferences.insert_space_before_opening_bracket_in_array_reference);
1006        if (this.preferences.insert_space_after_opening_bracket_in_array_reference) {
1007            this.scribe.space();
1008        }
1009        node.getIndex().accept(this);
1010        this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET, this.preferences.insert_space_before_closing_bracket_in_array_reference);
1011        return false;
1012    }
1013
1014    public boolean visit(ArrayCreation node) {
1015        this.scribe.printNextToken(TerminalTokens.TokenNamenew);
1016        this.scribe.space();
1017        final ArrayType type = node.getType();
1018        final List JavaDoc dimensions = node.dimensions();
1019        final int dimensionsLength = dimensions.size();
1020
1021        final int arrayTypeDimensions = type.getDimensions();
1022        type.getElementType().accept(this);
1023        if (dimensionsLength != 0) {
1024            for (int i = 0; i < dimensionsLength; i++) {
1025                this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET, this.preferences.insert_space_before_opening_bracket_in_array_allocation_expression);
1026                Expression dimension = (Expression) dimensions.get(i);
1027                if (dimension != null) {
1028                    if (this.preferences.insert_space_after_opening_bracket_in_array_allocation_expression) {
1029                        this.scribe.space();
1030                    }
1031                    dimension.accept(this);
1032                    this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET, this.preferences.insert_space_before_closing_bracket_in_array_allocation_expression);
1033                } else {
1034                    this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET, this.preferences.insert_space_between_empty_brackets_in_array_allocation_expression);
1035                }
1036            }
1037            for (int i = 0, max = arrayTypeDimensions - dimensionsLength; i < max; i++) {
1038                this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET, this.preferences.insert_space_before_opening_bracket_in_array_allocation_expression);
1039                this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET, this.preferences.insert_space_between_empty_brackets_in_array_allocation_expression);
1040            }
1041        } else {
1042            for (int i = 0; i < arrayTypeDimensions; i++) {
1043                this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET, this.preferences.insert_space_before_opening_bracket_in_array_allocation_expression);
1044                this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET, this.preferences.insert_space_between_empty_brackets_in_array_allocation_expression);
1045            }
1046        }
1047        
1048        final ArrayInitializer initializer = node.getInitializer();
1049        if (initializer != null) {
1050            initializer.accept(this);
1051        }
1052
1053        return false;
1054    }
1055
1056    public boolean visit(ArrayInitializer node) {
1057        final List JavaDoc expressions = node.expressions();
1058        final int expressionsLength = expressions.size();
1059        if (expressionsLength != 0) {
1060            final String JavaDoc array_initializer_brace_position = this.preferences.brace_position_for_array_initializer;
1061            formatOpeningBrace(array_initializer_brace_position, this.preferences.insert_space_before_opening_brace_in_array_initializer);
1062        
1063            final boolean insert_new_line_after_opening_brace = this.preferences.insert_new_line_after_opening_brace_in_array_initializer;
1064            if (expressionsLength > 1) {
1065                if (insert_new_line_after_opening_brace) {
1066                    this.scribe.printNewLine();
1067                }
1068                Alignment2 arrayInitializerAlignment = this.scribe.createAlignment(
1069                        "array_initializer",//$NON-NLS-1$
1070
this.preferences.alignment_for_expressions_in_array_initializer,
1071                        Alignment.R_OUTERMOST,
1072                        expressionsLength,
1073                        this.scribe.scanner.currentPosition,
1074                        this.preferences.continuation_indentation_for_array_initializer,
1075                        true);
1076                
1077                if (insert_new_line_after_opening_brace) {
1078                    arrayInitializerAlignment.fragmentIndentations[0] = arrayInitializerAlignment.breakIndentationLevel;
1079                }
1080                
1081                this.scribe.enterAlignment(arrayInitializerAlignment);
1082                boolean ok = false;
1083                do {
1084                    try {
1085                        this.scribe.alignFragment(arrayInitializerAlignment, 0);
1086                        if (this.preferences.insert_space_after_opening_brace_in_array_initializer) {
1087                            this.scribe.space();
1088                        }
1089                        ((Expression) expressions.get(0)).accept(this);
1090                        for (int i = 1; i < expressionsLength; i++) {
1091                            this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_array_initializer);
1092                            this.scribe.printTrailingComment();
1093                            this.scribe.alignFragment(arrayInitializerAlignment, i);
1094                            if (this.preferences.insert_space_after_comma_in_array_initializer) {
1095                                this.scribe.space();
1096                            }
1097                            ((Expression) expressions.get(i)).accept(this);
1098                            if (i == expressionsLength - 1) {
1099                                if (isNextToken(TerminalTokens.TokenNameCOMMA)) {
1100                                    this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_array_initializer);
1101                                    this.scribe.printTrailingComment();
1102                                }
1103                            }
1104                        }
1105                        ok = true;
1106                    } catch (AlignmentException e) {
1107                        this.scribe.redoAlignment(e);
1108                    }
1109                } while (!ok);
1110                this.scribe.exitAlignment(arrayInitializerAlignment, true);
1111            } else {
1112                if (insert_new_line_after_opening_brace) {
1113                    this.scribe.printNewLine();
1114                    this.scribe.indent();
1115                }
1116                // we don't need to use an alignment
1117
if (this.preferences.insert_space_after_opening_brace_in_array_initializer) {
1118                    this.scribe.space();
1119                } else {
1120                    this.scribe.needSpace = false;
1121                }
1122                ((Expression) expressions.get(0)).accept(this);
1123                if (isNextToken(TerminalTokens.TokenNameCOMMA)) {
1124                    this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_array_initializer);
1125                    this.scribe.printTrailingComment();
1126                }
1127                if (insert_new_line_after_opening_brace) {
1128                    this.scribe.unIndent();
1129                }
1130            }
1131            if (this.preferences.insert_new_line_before_closing_brace_in_array_initializer) {
1132                this.scribe.printNewLine();
1133            } else if (this.preferences.insert_space_before_closing_brace_in_array_initializer) {
1134                this.scribe.space();
1135            }
1136            this.scribe.printNextToken(TerminalTokens.TokenNameRBRACE, false);
1137            if (array_initializer_brace_position.equals(DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED)) {
1138                this.scribe.unIndent();
1139            }
1140        } else {
1141            boolean keepEmptyArrayInitializerOnTheSameLine = this.preferences.keep_empty_array_initializer_on_one_line;
1142            String JavaDoc array_initializer_brace_position = this.preferences.brace_position_for_array_initializer;
1143            if (keepEmptyArrayInitializerOnTheSameLine) {
1144                this.scribe.printNextToken(TerminalTokens.TokenNameLBRACE, this.preferences.insert_space_before_opening_brace_in_array_initializer);
1145                this.scribe.printNextToken(TerminalTokens.TokenNameRBRACE, this.preferences.insert_space_between_empty_braces_in_array_initializer);
1146            } else {
1147                formatOpeningBrace(array_initializer_brace_position, this.preferences.insert_space_before_opening_brace_in_array_initializer);
1148                this.scribe.printNextToken(TerminalTokens.TokenNameRBRACE, false);
1149                if (array_initializer_brace_position.equals(DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED)) {
1150                    this.scribe.unIndent();
1151                }
1152            }
1153        }
1154        return false;
1155    }
1156
1157    public boolean visit(ArrayType node) {
1158        node.getComponentType().accept(this);
1159        if (this.preferences.insert_space_before_opening_bracket_in_array_type_reference) {
1160            this.scribe.space();
1161        }
1162        this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET);
1163        if (this.preferences.insert_space_between_brackets_in_array_type_reference) {
1164            this.scribe.space();
1165        }
1166        this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET);
1167        return false;
1168    }
1169
1170    public boolean visit(AssertStatement node) {
1171        this.scribe.printNextToken(TerminalTokens.TokenNameassert);
1172        this.scribe.space();
1173        node.getExpression().accept(this);
1174        
1175        Expression message = node.getMessage();
1176        if (message != null) {
1177            this.scribe.printNextToken(TerminalTokens.TokenNameCOLON, this.preferences.insert_space_before_colon_in_assert);
1178            if (this.preferences.insert_space_after_colon_in_assert) {
1179                this.scribe.space();
1180            }
1181            message.accept(this);
1182        }
1183        this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
1184        this.scribe.printTrailingComment();
1185        return false;
1186    }
1187
1188    public boolean visit(Assignment node) {
1189        node.getLeftHandSide().accept(this);
1190        Assignment.Operator operator = node.getOperator();
1191        if (operator == Assignment.Operator.ASSIGN) {
1192            this.scribe.printNextToken(TerminalTokens.TokenNameEQUAL, this.preferences.insert_space_before_assignment_operator);
1193        } else if (operator == Assignment.Operator.MINUS_ASSIGN) {
1194            this.scribe.printNextToken(TerminalTokens.TokenNameMINUS_EQUAL, this.preferences.insert_space_before_assignment_operator);
1195        } else if (operator == Assignment.Operator.PLUS_ASSIGN) {
1196            this.scribe.printNextToken(TerminalTokens.TokenNamePLUS_EQUAL, this.preferences.insert_space_before_assignment_operator);
1197        } else if (operator == Assignment.Operator.TIMES_ASSIGN) {
1198            this.scribe.printNextToken(TerminalTokens.TokenNameMULTIPLY_EQUAL, this.preferences.insert_space_before_assignment_operator);
1199        } else if (operator == Assignment.Operator.DIVIDE_ASSIGN) {
1200            this.scribe.printNextToken(TerminalTokens.TokenNameDIVIDE_EQUAL, this.preferences.insert_space_before_assignment_operator);
1201        } else if (operator == Assignment.Operator.REMAINDER_ASSIGN) {
1202            this.scribe.printNextToken(TerminalTokens.TokenNameREMAINDER_EQUAL, this.preferences.insert_space_before_assignment_operator);
1203        } else if (operator == Assignment.Operator.LEFT_SHIFT_ASSIGN) {
1204            this.scribe.printNextToken(TerminalTokens.TokenNameLEFT_SHIFT_EQUAL, this.preferences.insert_space_before_assignment_operator);
1205        } else if (operator == Assignment.Operator.RIGHT_SHIFT_SIGNED_ASSIGN) {
1206            this.scribe.printNextToken(TerminalTokens.TokenNameRIGHT_SHIFT_EQUAL, this.preferences.insert_space_before_assignment_operator);
1207        } else if (operator == Assignment.Operator.RIGHT_SHIFT_UNSIGNED_ASSIGN) {
1208            this.scribe.printNextToken(TerminalTokens.TokenNameUNSIGNED_RIGHT_SHIFT_EQUAL, this.preferences.insert_space_before_assignment_operator);
1209        } else if (operator == Assignment.Operator.BIT_AND_ASSIGN) {
1210            this.scribe.printNextToken(TerminalTokens.TokenNameAND_EQUAL, this.preferences.insert_space_before_assignment_operator);
1211        } else if (operator == Assignment.Operator.BIT_OR_ASSIGN) {
1212            this.scribe.printNextToken(TerminalTokens.TokenNameOR_EQUAL, this.preferences.insert_space_before_assignment_operator);
1213        } else {
1214            this.scribe.printNextToken(TerminalTokens.TokenNameXOR_EQUAL, this.preferences.insert_space_before_assignment_operator);
1215        }
1216        if (this.preferences.insert_space_after_assignment_operator) {
1217            this.scribe.space();
1218        }
1219
1220        Alignment2 assignmentAlignment = this.scribe.createAlignment("assignmentAlignment", this.preferences.alignment_for_assignment, 1, this.scribe.scanner.currentPosition); //$NON-NLS-1$
1221
this.scribe.enterAlignment(assignmentAlignment);
1222        boolean ok = false;
1223        do {
1224            try {
1225                this.scribe.alignFragment(assignmentAlignment, 0);
1226                node.getRightHandSide().accept(this);
1227                ok = true;
1228            } catch(AlignmentException e){
1229                this.scribe.redoAlignment(e);
1230            }
1231        } while (!ok);
1232        this.scribe.exitAlignment(assignmentAlignment, true);
1233        return false;
1234    }
1235
1236    public boolean visit(Block node) {
1237        formatBlock(node, this.preferences.brace_position_for_block, this.preferences.insert_space_before_opening_brace_in_block);
1238        return false;
1239    }
1240
1241    public boolean visit(BooleanLiteral node) {
1242        if (node.booleanValue()) {
1243            this.scribe.printNextToken(TerminalTokens.TokenNametrue);
1244        } else {
1245            this.scribe.printNextToken(TerminalTokens.TokenNamefalse);
1246        }
1247        return false;
1248    }
1249
1250    public boolean visit(BreakStatement node) {
1251        this.scribe.printNextToken(TerminalTokens.TokenNamebreak);
1252        if (node.getLabel() != null) {
1253            this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, true);
1254        }
1255        this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
1256        this.scribe.printTrailingComment();
1257        return false;
1258    }
1259
1260    public boolean visit(CastExpression node) {
1261        this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN);
1262        if (this.preferences.insert_space_after_opening_paren_in_cast) {
1263            this.scribe.space();
1264        }
1265        node.getType().accept(this);
1266
1267        this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_cast);
1268        if (this.preferences.insert_space_after_closing_paren_in_cast) {
1269            this.scribe.space();
1270        }
1271        node.getExpression().accept(this);
1272        return false;
1273    }
1274
1275    public boolean visit(CharacterLiteral node) {
1276        this.scribe.printNextToken(TerminalTokens.TokenNameCharacterLiteral);
1277        return false;
1278    }
1279
1280    public boolean visit(ClassInstanceCreation node) {
1281        Expression expression = node.getExpression();
1282        if (expression != null) {
1283            expression.accept(this);
1284            this.scribe.printNextToken(TerminalTokens.TokenNameDOT);
1285        }
1286        this.scribe.printNextToken(TerminalTokens.TokenNamenew);
1287        final List JavaDoc typeArguments = node.typeArguments();
1288        final int length = typeArguments.size();
1289        if (length != 0) {
1290                this.scribe.printNextToken(TerminalTokens.TokenNameLESS, this.preferences.insert_space_before_opening_angle_bracket_in_type_arguments);
1291                if (this.preferences.insert_space_after_opening_angle_bracket_in_type_arguments) {
1292                    this.scribe.space();
1293                }
1294                for (int i = 0; i < length - 1; i++) {
1295                    ((Type) typeArguments.get(i)).accept(this);
1296                    this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_type_arguments);
1297                    if (this.preferences.insert_space_after_comma_in_type_arguments) {
1298                        this.scribe.space();
1299                    }
1300                }
1301                ((Type) typeArguments.get(length - 1)).accept(this);
1302                if (isClosingGenericToken()) {
1303                    this.scribe.printNextToken(CLOSING_GENERICS_EXPECTEDTOKENS, this.preferences.insert_space_before_closing_angle_bracket_in_type_arguments);
1304                }
1305                if (this.preferences.insert_space_after_closing_angle_bracket_in_type_arguments) {
1306                    this.scribe.space();
1307                }
1308        } else {
1309            this.scribe.space();
1310        }
1311
1312        node.getType().accept(this);
1313        
1314        this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_method_invocation);
1315
1316        final List JavaDoc arguments = node.arguments();
1317        final int argumentsLength = arguments.size();
1318        
1319        if (argumentsLength != 0) {
1320            if (this.preferences.insert_space_after_opening_paren_in_method_invocation) {
1321                this.scribe.space();
1322            }
1323            Alignment2 argumentsAlignment =this.scribe.createAlignment(
1324                    "allocation",//$NON-NLS-1$
1325
this.preferences.alignment_for_arguments_in_allocation_expression,
1326                    argumentsLength,
1327                    this.scribe.scanner.currentPosition);
1328            this.scribe.enterAlignment(argumentsAlignment);
1329            boolean ok = false;
1330            do {
1331                try {
1332                    for (int i = 0; i < argumentsLength; i++) {
1333                        if (i > 0) {
1334                            this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_allocation_expression);
1335                            this.scribe.printTrailingComment();
1336                        }
1337                        this.scribe.alignFragment(argumentsAlignment, i);
1338                        if (i > 0 && this.preferences.insert_space_after_comma_in_allocation_expression) {
1339                            this.scribe.space();
1340                        }
1341                        ((Expression) arguments.get(i)).accept(this);
1342                    }
1343                    ok = true;
1344                } catch (AlignmentException e) {
1345                    this.scribe.redoAlignment(e);
1346                }
1347            } while (!ok);
1348            this.scribe.exitAlignment(argumentsAlignment, true);
1349            this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_method_invocation);
1350        } else {
1351            this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_between_empty_parens_in_method_invocation);
1352        }
1353        final AnonymousClassDeclaration classDeclaration = node.getAnonymousClassDeclaration();
1354        if (classDeclaration != null) {
1355            classDeclaration.accept(this);
1356        }
1357        return false;
1358    }
1359
1360    public boolean visit(CompilationUnit node) {
1361        // fake new line to handle empty lines before package declaration or import declarations
1362
this.scribe.lastNumberOfNewLines = 1;
1363        /*
1364         * Package declaration
1365         */

1366        final PackageDeclaration packageDeclaration = node.getPackage();
1367        final boolean hasPackage = packageDeclaration != null;
1368        if (hasPackage) {
1369            if (hasComments()) {
1370                this.scribe.printComment();
1371            }
1372            int blankLinesBeforePackage = this.preferences.blank_lines_before_package;
1373            if (blankLinesBeforePackage > 0) {
1374                this.scribe.printEmptyLines(blankLinesBeforePackage);
1375            }
1376
1377            final List JavaDoc annotations = packageDeclaration.annotations();
1378            if (annotations.size() != 0) {
1379                this.scribe.printModifiers(annotations, this);
1380                this.scribe.space();
1381            }
1382            // dump the package keyword
1383
this.scribe.printNextToken(TerminalTokens.TokenNamepackage);
1384            this.scribe.space();
1385            packageDeclaration.getName().accept(this);
1386            this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
1387            this.scribe.printTrailingComment();
1388            int blankLinesAfterPackage = this.preferences.blank_lines_after_package;
1389            if (blankLinesAfterPackage > 0) {
1390                this.scribe.printEmptyLines(blankLinesAfterPackage);
1391            } else {
1392                this.scribe.printNewLine();
1393            }
1394        } else {
1395            this.scribe.printComment();
1396        }
1397        
1398        /*
1399         * Import statements
1400         */

1401        final List JavaDoc imports = node.imports();
1402        final int importsLength = imports.size();
1403        if (importsLength != 0) {
1404            if (hasPackage) {
1405                int blankLinesBeforeImports = this.preferences.blank_lines_before_imports;
1406                if (blankLinesBeforeImports > 0) {
1407                    this.scribe.printEmptyLines(blankLinesBeforeImports);
1408                }
1409            }
1410            for (int i = 0; i < importsLength; i++) {
1411                ((ImportDeclaration) imports.get(i)).accept(this);
1412            }
1413            
1414            int blankLinesAfterImports = this.preferences.blank_lines_after_imports;
1415            if (blankLinesAfterImports > 0) {
1416                this.scribe.printEmptyLines(blankLinesAfterImports);
1417            }
1418        }
1419
1420        formatEmptyTypeDeclaration(true);
1421        
1422        int blankLineBetweenTypeDeclarations = this.preferences.blank_lines_between_type_declarations;
1423        /*
1424         * Type declarations
1425         */

1426        final List JavaDoc types = node.types();
1427        final int typesLength = types.size();
1428        if (typesLength != 0) {
1429            for (int i = 0; i < typesLength - 1; i++) {
1430                ((AbstractTypeDeclaration) types.get(i)).accept(this);
1431                formatEmptyTypeDeclaration(false);
1432                if (blankLineBetweenTypeDeclarations != 0) {
1433                    this.scribe.printEmptyLines(blankLineBetweenTypeDeclarations);
1434                } else {
1435                    this.scribe.printNewLine();
1436                }
1437            }
1438            ((AbstractTypeDeclaration) types.get(typesLength - 1)).accept(this);
1439        }
1440        this.scribe.printEndOfCompilationUnit();
1441        return false;
1442    }
1443
1444    public boolean visit(ConditionalExpression node) {
1445        node.getExpression().accept(this);
1446    
1447        Alignment2 conditionalExpressionAlignment =this.scribe.createAlignment(
1448                "conditionalExpression", //$NON-NLS-1$
1449
this.preferences.alignment_for_conditional_expression,
1450                2,
1451                this.scribe.scanner.currentPosition);
1452    
1453        this.scribe.enterAlignment(conditionalExpressionAlignment);
1454        boolean ok = false;
1455        do {
1456            try {
1457                this.scribe.alignFragment(conditionalExpressionAlignment, 0);
1458                this.scribe.printNextToken(TerminalTokens.TokenNameQUESTION, this.preferences.insert_space_before_question_in_conditional);
1459    
1460                if (this.preferences.insert_space_after_question_in_conditional) {
1461                    this.scribe.space();
1462                }
1463                node.getThenExpression().accept(this);
1464                this.scribe.printTrailingComment();
1465                this.scribe.alignFragment(conditionalExpressionAlignment, 1);
1466                this.scribe.printNextToken(TerminalTokens.TokenNameCOLON, this.preferences.insert_space_before_colon_in_conditional);
1467    
1468                if (this.preferences.insert_space_after_colon_in_conditional) {
1469                    this.scribe.space();
1470                }
1471                node.getElseExpression().accept(this);
1472    
1473                ok = true;
1474            } catch (AlignmentException e) {
1475                this.scribe.redoAlignment(e);
1476            }
1477        } while (!ok);
1478        this.scribe.exitAlignment(conditionalExpressionAlignment, true);
1479        return false;
1480    }
1481
1482    public boolean visit(ConstructorInvocation node) {
1483        final List JavaDoc typeArguments = node.typeArguments();
1484        final int typeArgumentsLength = typeArguments.size();
1485        if (typeArgumentsLength != 0) {
1486                this.scribe.printNextToken(TerminalTokens.TokenNameLESS, this.preferences.insert_space_before_opening_angle_bracket_in_type_arguments);
1487                if (this.preferences.insert_space_after_opening_angle_bracket_in_type_arguments) {
1488                    this.scribe.space();
1489                }
1490                for (int i = 0; i < typeArgumentsLength - 1; i++) {
1491                    ((Type) typeArguments.get(i)).accept(this);
1492                    this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_type_arguments);
1493                    if (this.preferences.insert_space_after_comma_in_type_arguments) {
1494                        this.scribe.space();
1495                    }
1496                }
1497                ((Type) typeArguments.get(typeArgumentsLength - 1)).accept(this);
1498                if (isClosingGenericToken()) {
1499                    this.scribe.printNextToken(CLOSING_GENERICS_EXPECTEDTOKENS, this.preferences.insert_space_before_closing_angle_bracket_in_type_arguments);
1500                }
1501                if (this.preferences.insert_space_after_closing_angle_bracket_in_type_arguments) {
1502                    this.scribe.space();
1503                }
1504        }
1505        
1506        this.scribe.printNextToken(TerminalTokens.TokenNamethis);
1507        this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_method_invocation);
1508        
1509        final List JavaDoc arguments = node.arguments();
1510        final int argumentsLength = arguments.size();
1511        if (argumentsLength != 0) {
1512            if (this.preferences.insert_space_after_opening_paren_in_method_invocation) {
1513                this.scribe.space();
1514            }
1515            Alignment2 argumentsAlignment =this.scribe.createAlignment(
1516                    "explicit_constructor_call",//$NON-NLS-1$
1517
this.preferences.alignment_for_arguments_in_explicit_constructor_call,
1518                    argumentsLength,
1519                    this.scribe.scanner.currentPosition);
1520            this.scribe.enterAlignment(argumentsAlignment);
1521            boolean ok = false;
1522            do {
1523                try {
1524                    for (int i = 0; i < argumentsLength; i++) {
1525                        if (i > 0) {
1526                            this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_explicit_constructor_call_arguments);
1527                            this.scribe.printTrailingComment();
1528                        }
1529                        this.scribe.alignFragment(argumentsAlignment, i);
1530                        if (i > 0 && this.preferences.insert_space_after_comma_in_explicit_constructor_call_arguments) {
1531                            this.scribe.space();
1532                        }
1533                        ((Expression) arguments.get(i)).accept(this);
1534                    }
1535                    ok = true;
1536                } catch (AlignmentException e) {
1537                    this.scribe.redoAlignment(e);
1538                }
1539            } while (!ok);
1540            this.scribe.exitAlignment(argumentsAlignment, true);
1541            this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_method_invocation);
1542        } else {
1543            this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_between_empty_parens_in_method_invocation);
1544        }
1545        this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
1546        this.scribe.printTrailingComment();
1547        return false;
1548    }
1549
1550    public boolean visit(ContinueStatement node) {
1551        this.scribe.printNextToken(TerminalTokens.TokenNamecontinue);
1552        if (node.getLabel() != null) {
1553            this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, true);
1554        }
1555        this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
1556        this.scribe.printTrailingComment();
1557        return false;
1558    }
1559
1560    public boolean visit(DoStatement node) {
1561        this.scribe.printNextToken(TerminalTokens.TokenNamedo);
1562        final int line = this.scribe.line;
1563        
1564        final Statement action = node.getBody();
1565        if (action != null) {
1566            switch(action.getNodeType()) {
1567                case ASTNode.BLOCK :
1568                    formatLeftCurlyBrace(line, this.preferences.brace_position_for_block);
1569                    action.accept(this);
1570                    break;
1571                case ASTNode.EMPTY_STATEMENT :
1572                    action.accept(this);
1573                    break;
1574                default :
1575                    this.scribe.printNewLine();
1576                    this.scribe.indent();
1577                    action.accept(this);
1578                    this.scribe.unIndent();
1579                    this.scribe.printNewLine();
1580            }
1581        } else {
1582            action.accept(this);
1583        }
1584
1585        if (this.preferences.insert_new_line_before_while_in_do_statement) {
1586            this.scribe.printNewLine();
1587        }
1588        this.scribe.printNextToken(TerminalTokens.TokenNamewhile, this.preferences.insert_space_after_closing_brace_in_block);
1589        this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_while);
1590        
1591        if (this.preferences.insert_space_after_opening_paren_in_while) {
1592            this.scribe.space();
1593        }
1594        
1595        node.getExpression().accept(this);
1596        
1597        this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_while);
1598        this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
1599        this.scribe.printTrailingComment();
1600        return false;
1601    }
1602
1603    public boolean visit(EmptyStatement node) {
1604        if (this.preferences.put_empty_statement_on_new_line) {
1605            this.scribe.printNewLine();
1606        }
1607        this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
1608        this.scribe.printTrailingComment();
1609        return false;
1610    }
1611
1612    public boolean visit(EnhancedForStatement node) {
1613        this.scribe.printNextToken(TerminalTokens.TokenNamefor);
1614        final int line = this.scribe.line;
1615        this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_for);
1616        
1617        if (this.preferences.insert_space_after_opening_paren_in_for) {
1618            this.scribe.space();
1619        }
1620        node.getParameter().accept(this);
1621
1622        this.scribe.printNextToken(TerminalTokens.TokenNameCOLON, this.preferences.insert_space_before_colon_in_for);
1623        if (this.preferences.insert_space_after_colon_in_for) {
1624            this.scribe.space();
1625        }
1626        node.getExpression().accept(this);
1627
1628        this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_for);
1629        
1630        formatAction(line, node.getBody(), false);
1631        return false;
1632    }
1633
1634    public boolean visit(EnumConstantDeclaration node) {
1635        this.scribe.printComment();
1636        final int line = this.scribe.line;
1637        
1638        final List JavaDoc modifiers = node.modifiers();
1639        if (modifiers.size() != 0) {
1640            this.scribe.printModifiers(modifiers, this);
1641            this.scribe.space();
1642        }
1643        this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier);
1644        if (isNextToken(TerminalTokens.TokenNameLPAREN)) {
1645            this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_enum_constant);
1646            final List JavaDoc arguments = node.arguments();
1647            final int argumentsLength = arguments.size();
1648            if (argumentsLength != 0) {
1649                Alignment2 argumentsAlignment = this.scribe.createAlignment(
1650                        "enumConstantArguments",//$NON-NLS-1$
1651
this.preferences.alignment_for_arguments_in_enum_constant,
1652                        argumentsLength,
1653                        this.scribe.scanner.currentPosition);
1654                this.scribe.enterAlignment(argumentsAlignment);
1655                boolean ok = false;
1656                do {
1657                    try {
1658                        if (this.preferences.insert_space_after_opening_paren_in_enum_constant) {
1659                            this.scribe.space();
1660                        }
1661                        for (int i = 0; i < argumentsLength; i++) {
1662                            if (i > 0) {
1663                                this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_enum_constant_arguments);
1664                                this.scribe.printTrailingComment();
1665                            }
1666                            this.scribe.alignFragment(argumentsAlignment, i);
1667                            if (i > 0 && this.preferences.insert_space_after_comma_in_enum_constant_arguments) {
1668                                this.scribe.space();
1669                            }
1670                            ((Expression) arguments.get(i)).accept(this);
1671                        }
1672                        ok = true;
1673                    } catch (AlignmentException e) {
1674                        this.scribe.redoAlignment(e);
1675                    }
1676                } while (!ok);
1677                this.scribe.exitAlignment(argumentsAlignment, true);
1678            
1679                this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_enum_constant);
1680            } else {
1681                this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_between_empty_parens_in_enum_constant);
1682            }
1683        }
1684
1685        final AnonymousClassDeclaration anonymousClassDeclaration = node.getAnonymousClassDeclaration();
1686        if (anonymousClassDeclaration != null) {
1687            final List JavaDoc bodyDeclarations = anonymousClassDeclaration.bodyDeclarations();
1688            String JavaDoc enum_constant_brace = this.preferences.brace_position_for_enum_constant;
1689            
1690            formatLeftCurlyBrace(line, enum_constant_brace);
1691            formatTypeOpeningBrace(enum_constant_brace, this.preferences.insert_space_before_opening_brace_in_enum_constant, bodyDeclarations.size() != 0, node);
1692            
1693            if (this.preferences.indent_body_declarations_compare_to_enum_constant_header) {
1694                this.scribe.indent();
1695            }
1696
1697            formatTypeMembers(bodyDeclarations, true);
1698
1699            if (this.preferences.indent_body_declarations_compare_to_enum_constant_header) {
1700                this.scribe.unIndent();
1701            }
1702            
1703            if (this.preferences.insert_new_line_in_empty_enum_constant) {
1704                this.scribe.printNewLine();
1705            }
1706            this.scribe.printNextToken(TerminalTokens.TokenNameRBRACE);
1707            if (enum_constant_brace.equals(DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED)) {
1708                this.scribe.unIndent();
1709            }
1710            if (hasComments()) {
1711                this.scribe.printNewLine();
1712            }
1713        }
1714        return false;
1715    }
1716    
1717    
1718    public boolean visit(EnumDeclaration node) {
1719        /*
1720         * Print comments to get proper line number
1721         */

1722        this.scribe.printComment();
1723        final int line = this.scribe.line;
1724        
1725        final List JavaDoc modifiers = node.modifiers();
1726        if (modifiers.size() != 0) {
1727            this.scribe.printModifiers(modifiers, this);
1728            this.scribe.space();
1729        }
1730            
1731        this.scribe.printNextToken(TerminalTokens.TokenNameenum, true);
1732
1733        this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, true);
1734
1735        /*
1736         * Super Interfaces
1737         */

1738        final List JavaDoc superInterfaces = node.superInterfaceTypes();
1739        final int superInterfacesLength = superInterfaces.size();
1740        if (superInterfacesLength != 0) {
1741            Alignment2 interfaceAlignment =this.scribe.createAlignment(
1742                    "superInterfaces",//$NON-NLS-1$
1743
this.preferences.alignment_for_superinterfaces_in_enum_declaration,
1744                    superInterfacesLength+1, // implements token is first fragment
1745
this.scribe.scanner.currentPosition);
1746            this.scribe.enterAlignment(interfaceAlignment);
1747            boolean ok = false;
1748            do {
1749                try {
1750                    this.scribe.alignFragment(interfaceAlignment, 0);
1751                    this.scribe.printNextToken(TerminalTokens.TokenNameimplements, true);
1752                    for (int i = 0; i < superInterfacesLength; i++) {
1753                        if (i > 0) {
1754                            this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_superinterfaces);
1755                            this.scribe.printTrailingComment();
1756                            this.scribe.alignFragment(interfaceAlignment, i+1);
1757                            if (this.preferences.insert_space_after_comma_in_superinterfaces) {
1758                                this.scribe.space();
1759                            }
1760                            ((Type) superInterfaces.get(i)).accept(this);
1761                        } else {
1762                            this.scribe.alignFragment(interfaceAlignment, i+1);
1763                            this.scribe.space();
1764                            ((Type) superInterfaces.get(i)).accept(this);
1765                        }
1766                    }
1767                    ok = true;
1768                } catch (AlignmentException e) {
1769                    this.scribe.redoAlignment(e);
1770                }
1771            } while (!ok);
1772            this.scribe.exitAlignment(interfaceAlignment, true);
1773        }
1774        
1775        final String JavaDoc bracePosition = this.preferences.brace_position_for_enum_declaration;
1776
1777        final List JavaDoc enumConstants = node.enumConstants();
1778        final int enumConstantsLength = enumConstants.size();
1779
1780        formatLeftCurlyBrace(line, bracePosition);
1781        formatTypeOpeningBrace(bracePosition, this.preferences.insert_space_before_opening_brace_in_enum_declaration, (enumConstantsLength + node.bodyDeclarations().size()) != 0, node);
1782        
1783        final boolean indent_body_declarations_compare_to_header = this.preferences.indent_body_declarations_compare_to_enum_declaration_header;
1784        if (indent_body_declarations_compare_to_header) {
1785            this.scribe.indent();
1786        }
1787        
1788        if (enumConstantsLength != 0) {
1789            if (enumConstantsLength > 1) {
1790                Alignment2 enumConstantsAlignment = this.scribe.createAlignment(
1791                        "enumConstants",//$NON-NLS-1$
1792
this.preferences.alignment_for_enum_constants,
1793                        enumConstantsLength,
1794                        this.scribe.scanner.currentPosition,
1795                        0, // we don't want to indent enum constants when splitting to a new line
1796
false);
1797                this.scribe.enterAlignment(enumConstantsAlignment);
1798                boolean ok = false;
1799                do {
1800                    try {
1801                        for (int i = 0; i < enumConstantsLength; i++) {
1802                            this.scribe.alignFragment(enumConstantsAlignment, i);
1803                            final EnumConstantDeclaration enumConstantDeclaration = ((EnumConstantDeclaration) enumConstants.get(i));
1804                            enumConstantDeclaration.accept(this);
1805                            if (isNextToken(TerminalTokens.TokenNameCOMMA)) {
1806                                this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_enum_declarations);
1807                                if (this.preferences.insert_space_after_comma_in_enum_declarations) {
1808                                    this.scribe.space();
1809                                }
1810                                this.scribe.printTrailingComment();
1811                                if (enumConstantDeclaration.getAnonymousClassDeclaration() != null) {
1812                                    this.scribe.printNewLine();
1813                                }
1814                            }
1815                        }
1816                        ok = true;
1817                    } catch (AlignmentException e) {
1818                        this.scribe.redoAlignment(e);
1819                    }
1820                } while (!ok);
1821                this.scribe.exitAlignment(enumConstantsAlignment, true);
1822            } else {
1823                final EnumConstantDeclaration enumConstantDeclaration = ((EnumConstantDeclaration) enumConstants.get(0));
1824                enumConstantDeclaration.accept(this);
1825                if (isNextToken(TerminalTokens.TokenNameCOMMA)) {
1826                    this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_enum_declarations);
1827                    if (this.preferences.insert_space_after_comma_in_enum_declarations) {
1828                        this.scribe.space();
1829                    }
1830                    this.scribe.printTrailingComment();
1831                    if (enumConstantDeclaration.getAnonymousClassDeclaration() != null) {
1832                        this.scribe.printNewLine();
1833                    }
1834                }
1835            }
1836        }
1837        if (isNextToken(TerminalTokens.TokenNameSEMICOLON)) {
1838            this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
1839            this.scribe.printTrailingComment();
1840        }
1841        if (enumConstantsLength != 0) {
1842            this.scribe.printNewLine();
1843        }
1844
1845        formatTypeMembers(node.bodyDeclarations(), true);
1846        
1847        if (indent_body_declarations_compare_to_header) {
1848            this.scribe.unIndent();
1849        }
1850        
1851        if (this.preferences.insert_new_line_in_empty_enum_declaration) {
1852            this.scribe.printNewLine();
1853        }
1854        this.scribe.printNextToken(TerminalTokens.TokenNameRBRACE);
1855        this.scribe.printTrailingComment();
1856        if (bracePosition.equals(DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED)) {
1857            this.scribe.unIndent();
1858        }
1859        if (hasComments()) {
1860            this.scribe.printNewLine();
1861        }
1862        return false;
1863    }
1864
1865    public boolean visit(ExpressionStatement node) {
1866        node.getExpression().accept(this);
1867        this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
1868        this.scribe.printTrailingComment();
1869        return false;
1870    }
1871
1872    public boolean visit(FieldAccess node) {
1873        node.getExpression().accept(this);
1874        this.scribe.printNextToken(TerminalTokens.TokenNameDOT);
1875        this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier);
1876        return false;
1877    }
1878
1879    public boolean visit(ForStatement node) {
1880        this.scribe.printNextToken(TerminalTokens.TokenNamefor);
1881        final int line = this.scribe.line;
1882        this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_for);
1883        
1884        if (this.preferences.insert_space_after_opening_paren_in_for) {
1885            this.scribe.space();
1886        }
1887        final List JavaDoc initializers = node.initializers();
1888        final int initializersLength = initializers.size();
1889        if (initializersLength != 0) {
1890            for (int i = 0; i < initializersLength; i++) {
1891                Expression initializer = (Expression) initializers.get(i);
1892                switch(initializer.getNodeType()) {
1893                    case ASTNode.VARIABLE_DECLARATION_EXPRESSION :
1894                        formatLocalDeclaration((VariableDeclarationExpression) initializer, this.preferences.insert_space_before_comma_in_for_inits, this.preferences.insert_space_after_comma_in_for_inits);
1895                        break;
1896                    default:
1897                        initializer.accept(this);
1898                        if (i >= 0 && (i < initializersLength - 1)) {
1899                            this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_for_inits);
1900                            if (this.preferences.insert_space_after_comma_in_for_inits) {
1901                                this.scribe.space();
1902                            }
1903                            this.scribe.printTrailingComment();
1904                        }
1905                }
1906            }
1907        }
1908        this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon_in_for);
1909        final Expression condition = node.getExpression();
1910        if (condition != null) {
1911            if (this.preferences.insert_space_after_semicolon_in_for) {
1912                this.scribe.space();
1913            }
1914            condition.accept(this);
1915        }
1916        this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon_in_for);
1917        final List JavaDoc updaters = node.updaters();
1918        final int updatersLength = updaters.size();
1919        if (updatersLength != 0) {
1920            if (this.preferences.insert_space_after_semicolon_in_for) {
1921                this.scribe.space();
1922            }
1923            for (int i = 0; i < updatersLength; i++) {
1924                ((Expression) updaters.get(i)).accept(this);
1925                if (i != updatersLength - 1) {
1926                    this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_for_increments);
1927                    if (this.preferences.insert_space_after_comma_in_for_increments) {
1928                        this.scribe.space();
1929                    }
1930                    this.scribe.printTrailingComment();
1931                }
1932            }
1933        }
1934        this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_for);
1935        
1936        formatAction(line, node.getBody(), false);
1937        return false;
1938    }
1939
1940    public boolean visit(IfStatement node) {
1941        this.scribe.printNextToken(TerminalTokens.TokenNameif);
1942        final int line = this.scribe.line;
1943        this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_if);
1944        if (this.preferences.insert_space_after_opening_paren_in_if) {
1945            this.scribe.space();
1946        }
1947        node.getExpression().accept(this);
1948        this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_if);
1949
1950        final Statement thenStatement = node.getThenStatement();
1951        final Statement elseStatement = node.getElseStatement();
1952
1953        boolean thenStatementIsBlock = false;
1954        if (thenStatement != null) {
1955            if (thenStatement instanceof Block) {
1956                final Block block = (Block) thenStatement;
1957                thenStatementIsBlock = true;
1958                final List JavaDoc statements = block.statements();
1959                if (isGuardClause(block, statements) && elseStatement == null && this.preferences.keep_guardian_clause_on_one_line) {
1960                    /*
1961                     * Need a specific formatting for guard clauses
1962                     * guard clauses are block with a single return or throw
1963                     * statement
1964                     */

1965                    this.scribe.printNextToken(TerminalTokens.TokenNameLBRACE, this.preferences.insert_space_before_opening_brace_in_block);
1966                    this.scribe.space();
1967                    ((Statement) statements.get(0)).accept(this);
1968                    this.scribe.printNextToken(TerminalTokens.TokenNameRBRACE, true);
1969                    this.scribe.printTrailingComment();
1970                } else {
1971                    formatLeftCurlyBrace(line, this.preferences.brace_position_for_block);
1972                    thenStatement.accept(this);
1973                    if (elseStatement != null && (this.preferences.insert_new_line_before_else_in_if_statement)) {
1974                        this.scribe.printNewLine();
1975                    }
1976                }
1977            } else if (elseStatement == null && this.preferences.keep_simple_if_on_one_line) {
1978                Alignment2 compactIfAlignment = this.scribe.createAlignment(
1979                        "compactIf", //$NON-NLS-1$
1980
this.preferences.alignment_for_compact_if,
1981                        Alignment.R_OUTERMOST,
1982                        1,
1983                        this.scribe.scanner.currentPosition,
1984                        1,
1985                        false);
1986                this.scribe.enterAlignment(compactIfAlignment);
1987                boolean ok = false;
1988                do {
1989                    try {
1990                        this.scribe.alignFragment(compactIfAlignment, 0);
1991                        this.scribe.space();
1992                        thenStatement.accept(this);
1993                        ok = true;
1994                    } catch (AlignmentException e) {
1995                        this.scribe.redoAlignment(e);
1996                    }
1997                } while (!ok);
1998                this.scribe.exitAlignment(compactIfAlignment, true);
1999            } else if (this.preferences.keep_then_statement_on_same_line) {
2000                this.scribe.space();
2001                thenStatement.accept(this);
2002                if (elseStatement != null) {
2003                    this.scribe.printNewLine();
2004                }
2005            } else {
2006                this.scribe.printTrailingComment();
2007                this.scribe.printNewLine();
2008                this.scribe.indent();
2009                thenStatement.accept(this);
2010                if (elseStatement != null) {
2011                    this.scribe.printNewLine();
2012                }
2013                this.scribe.unIndent();
2014            }
2015        }
2016        
2017        if (elseStatement != null) {
2018            if (thenStatementIsBlock) {
2019                this.scribe.printNextToken(TerminalTokens.TokenNameelse, this.preferences.insert_space_after_closing_brace_in_block);
2020            } else {
2021                this.scribe.printNextToken(TerminalTokens.TokenNameelse, true);
2022            }
2023            if (elseStatement instanceof Block) {
2024                elseStatement.accept(this);
2025            } else if (elseStatement instanceof IfStatement) {
2026                if (!this.preferences.compact_else_if) {
2027                    this.scribe.printNewLine();
2028                    this.scribe.indent();
2029                }
2030                this.scribe.space();
2031                elseStatement.accept(this);
2032                if (!this.preferences.compact_else_if) {
2033                    this.scribe.unIndent();
2034                }
2035            } else if (this.preferences.keep_else_statement_on_same_line) {
2036                this.scribe.space();
2037                elseStatement.accept(this);
2038            } else {
2039                this.scribe.printNewLine();
2040                this.scribe.indent();
2041                elseStatement.accept(this);
2042                this.scribe.unIndent();
2043            }
2044        }
2045        return false;
2046    }
2047
2048    public boolean visit(ImportDeclaration node) {
2049        this.scribe.printNextToken(TerminalTokens.TokenNameimport);
2050        this.scribe.space();
2051        if (node.isStatic()) {
2052            this.scribe.printNextToken(TerminalTokens.TokenNamestatic);
2053            this.scribe.space();
2054        }
2055        node.getName().accept(this);
2056        if (node.isOnDemand()) {
2057            this.scribe.printNextToken(TerminalTokens.TokenNameDOT);
2058            this.scribe.printNextToken(TerminalTokens.TokenNameMULTIPLY);
2059        }
2060        this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
2061        this.scribe.printTrailingComment();
2062        this.scribe.printNewLine();
2063        return false;
2064    }
2065
2066    public boolean visit(InfixExpression node) {
2067        // active line wrapping
2068
final InfixExpressionWrappingBuilder builder = new InfixExpressionWrappingBuilder();
2069        node.accept(builder);
2070        final int fragmentsSize = builder.getFragmentsCounter();
2071        this.scribe.printComment();
2072        Alignment2 binaryExpressionAlignment = this.scribe.createAlignment("binaryExpressionAlignment", this.preferences.alignment_for_binary_expression, Alignment.R_OUTERMOST, fragmentsSize, this.scribe.scanner.currentPosition); //$NON-NLS-1$
2073
this.scribe.enterAlignment(binaryExpressionAlignment);
2074        boolean ok = false;
2075        List JavaDoc fragments = builder.fragments;
2076        int[] operators = builder.getOperators();
2077/* do {
2078            try {
2079                final boolean alignAfterOperator = false;
2080                if (alignAfterOperator) {
2081                    for (int i = 0; i < fragmentsSize - 1; i++) {
2082                        this.scribe.alignFragment(binaryExpressionAlignment, i);
2083                        ((Expression) fragments.get(i)).accept(this);
2084                        this.scribe.printTrailingComment();
2085                        if (this.scribe.lastNumberOfNewLines == 1) {
2086                            // a new line has been inserted by printTrailingComment()
2087                            this.scribe.indentationLevel = binaryExpressionAlignment.breakIndentationLevel;
2088                        }
2089                        this.scribe.printNextToken(operators[i], this.preferences.insert_space_before_binary_operator);
2090                        if (operators[i] == TerminalTokens.TokenNameMINUS && isNextToken(TerminalTokens.TokenNameMINUS)) {
2091                            // the next character is a minus (unary operator)
2092                            this.scribe.space();
2093                        }
2094                        if (this.preferences.insert_space_after_binary_operator) {
2095                            this.scribe.space();
2096                        }
2097                    }
2098                    this.scribe.alignFragment(binaryExpressionAlignment, fragmentsSize - 1);
2099                    ((Expression) fragments.get(fragmentsSize - 1)).accept(this);
2100                    this.scribe.printTrailingComment();
2101                } else {
2102                    this.scribe.alignFragment(binaryExpressionAlignment, 0);
2103                    ((Expression) fragments.get(0)).accept(this);
2104                    this.scribe.printTrailingComment();
2105                    if (this.scribe.lastNumberOfNewLines == 1) {
2106                        if (binaryExpressionAlignment.couldBreak() && binaryExpressionAlignment.wasSplit) {
2107                            binaryExpressionAlignment.performFragmentEffect();
2108                        }
2109                    }
2110                    for (int i = 1; i < fragmentsSize - 1; i++) {
2111                        this.scribe.alignFragment(binaryExpressionAlignment, i);
2112                        this.scribe.printNextToken(operators[i - 1], this.preferences.insert_space_before_binary_operator);
2113                        if (operators[i] == TerminalTokens.TokenNameMINUS && isNextToken(TerminalTokens.TokenNameMINUS)) {
2114                            // the next character is a minus (unary operator)
2115                            this.scribe.space();
2116                        }
2117                        if (this.preferences.insert_space_after_binary_operator) {
2118                            this.scribe.space();
2119                        }
2120                        ((Expression) fragments.get(i)).accept(this);
2121                        this.scribe.printTrailingComment();
2122                        if (this.scribe.lastNumberOfNewLines == 1) {
2123                            if (binaryExpressionAlignment.couldBreak() && binaryExpressionAlignment.wasSplit) {
2124                                binaryExpressionAlignment.performFragmentEffect();
2125                            }
2126                        }
2127                    }
2128                    this.scribe.alignFragment(binaryExpressionAlignment, fragmentsSize - 1);
2129                    this.scribe.printNextToken(operators[fragmentsSize - 2], this.preferences.insert_space_before_binary_operator);
2130                    if (operators[fragmentsSize - 2] == TerminalTokens.TokenNameMINUS && isNextToken(TerminalTokens.TokenNameMINUS)) {
2131                        // the next character is a minus (unary operator)
2132                        this.scribe.space();
2133                    }
2134                    if (this.preferences.insert_space_after_binary_operator) {
2135                        this.scribe.space();
2136                    }
2137                    ((Expression) fragments.get(fragmentsSize - 1)).accept(this);
2138                    this.scribe.printTrailingComment();
2139                    if (this.scribe.lastNumberOfNewLines == 1) {
2140                        if (binaryExpressionAlignment.couldBreak() && binaryExpressionAlignment.wasSplit) {
2141                            binaryExpressionAlignment.performFragmentEffect();
2142                        }
2143                    }
2144                }
2145                ok = true;
2146            } catch(AlignmentException e){
2147                this.scribe.redoAlignment(e);
2148            }
2149        } while (!ok);
2150        this.scribe.exitAlignment(binaryExpressionAlignment, true);*/

2151        do {
2152            try {
2153                for (int i = 0; i < fragmentsSize - 1; i++) {
2154                    ((Expression) fragments.get(i)).accept(this);
2155                    this.scribe.printTrailingComment();
2156                    if (this.scribe.lastNumberOfNewLines == 1) {
2157                        if (binaryExpressionAlignment.couldBreak() && binaryExpressionAlignment.wasSplit) {
2158                            binaryExpressionAlignment.performFragmentEffect();
2159                        }
2160                    }
2161                    this.scribe.alignFragment(binaryExpressionAlignment, i);
2162                    this.scribe.printNextToken(operators[i], this.preferences.insert_space_before_binary_operator);
2163                    this.scribe.printTrailingComment();
2164                    if (this.scribe.lastNumberOfNewLines == 1) {
2165                        if (binaryExpressionAlignment.couldBreak() && binaryExpressionAlignment.wasSplit) {
2166                            binaryExpressionAlignment.performFragmentEffect();
2167                        }
2168                    }
2169                    if ( this.preferences.insert_space_after_binary_operator
2170                            || (operators[i] == TerminalTokens.TokenNameMINUS && isNextToken(TerminalTokens.TokenNameMINUS))) {
2171                        // the next character is a minus (unary operator) or the preference is set to true
2172
this.scribe.space();
2173                    }
2174                }
2175                ((Expression) fragments.get(fragmentsSize - 1)).accept(this);
2176                this.scribe.printTrailingComment();
2177                if (this.scribe.lastNumberOfNewLines == 1) {
2178                    if (binaryExpressionAlignment.couldBreak() && binaryExpressionAlignment.wasSplit) {
2179                        binaryExpressionAlignment.performFragmentEffect();
2180                    }
2181                }
2182                ok = true;
2183            } catch(AlignmentException e){
2184                this.scribe.redoAlignment(e);
2185            }
2186        } while (!ok);
2187        this.scribe.exitAlignment(binaryExpressionAlignment, true);
2188/* leftOperand.accept(this);
2189            final int operator = extractInfixExpressionOperator(node);
2190            this.scribe.printNextToken(operator, this.preferences.insert_space_before_binary_operator);
2191            if ( this.preferences.insert_space_after_binary_operator
2192                    || (operator == TerminalTokens.TokenNameMINUS && isNextToken(TerminalTokens.TokenNameMINUS))) {
2193                // the next character is a minus (unary operator) or the preference is set to true
2194                this.scribe.space();
2195            }
2196            rightOperand.accept(this);*/

2197        return false;
2198    }
2199
2200    public boolean visit(Initializer node) {
2201        final List JavaDoc modifiers = node.modifiers();
2202        if (modifiers.size() != 0) {
2203            this.scribe.printModifiers(modifiers, this);
2204            this.scribe.space();
2205        }
2206        node.getBody().accept(this);
2207        return false;
2208    }
2209
2210    public boolean visit(InstanceofExpression node) {
2211        node.getLeftOperand().accept(this);
2212        this.scribe.printNextToken(TerminalTokens.TokenNameinstanceof, true);
2213        this.scribe.space();
2214        node.getRightOperand().accept(this);
2215        return false;
2216    }
2217
2218    public boolean visit(LabeledStatement node) {
2219        this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier);
2220        this.scribe.printNextToken(TerminalTokens.TokenNameCOLON, this.preferences.insert_space_before_colon_in_labeled_statement);
2221        if (this.preferences.insert_space_after_colon_in_labeled_statement) {
2222            this.scribe.space();
2223        }
2224        node.getBody().accept(this);
2225        return false;
2226    }
2227    
2228    public boolean visit(MarkerAnnotation node) {
2229        this.scribe.printNextToken(TerminalTokens.TokenNameAT);
2230        if (this.preferences.insert_space_after_at_in_annotation) {
2231            this.scribe.space();
2232        }
2233        node.getTypeName().accept(this);
2234        return false;
2235    }
2236
2237    public boolean visit(MemberValuePair node) {
2238        this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier);
2239        this.scribe.printNextToken(TerminalTokens.TokenNameEQUAL, this.preferences.insert_space_before_assignment_operator);
2240        if (this.preferences.insert_space_after_assignment_operator) {
2241            this.scribe.space();
2242        }
2243        node.getValue().accept(this);
2244        return false;
2245    }
2246
2247    public boolean visit(MethodDeclaration node) {
2248        if ((node.getFlags() & ASTNode.MALFORMED) != 0) {
2249            this.scribe.printComment();
2250            this.scribe.printIndentationIfNecessary();
2251            this.scribe.scanner.resetTo(node.getStartPosition() + node.getLength(), this.scribe.scannerEndPosition);
2252            this.scribe.needSpace = true;
2253            this.scribe.printTrailingComment();
2254            switch(this.scribe.scanner.source[this.scribe.scanner.currentPosition]) {
2255                case '\n' :
2256                    this.scribe.scanner.currentPosition++;
2257                    this.scribe.lastNumberOfNewLines = 1;
2258                    break;
2259                case '\r' :
2260                    this.scribe.scanner.currentPosition++;
2261                    if (this.scribe.scanner.source[this.scribe.scanner.currentPosition] == '\n') {
2262                        this.scribe.scanner.currentPosition++;
2263                    }
2264                    this.scribe.lastNumberOfNewLines = 1;
2265            }
2266            return false;
2267        }
2268        /*
2269         * Print comments to get proper line number
2270         */

2271        this.scribe.printComment();
2272        final int line = this.scribe.line;
2273        
2274        final List JavaDoc modifiers = node.modifiers();
2275        final int modifiersLength = modifiers.size();
2276        if (modifiersLength != 0) {
2277            this.scribe.printModifiers(modifiers, this);
2278            this.scribe.space();
2279        }
2280        
2281        final List JavaDoc typeParameters = node.typeParameters();
2282        final int typeParametersLength = typeParameters.size();
2283        if (typeParametersLength != 0) {
2284            this.scribe.printNextToken(TerminalTokens.TokenNameLESS, this.preferences.insert_space_before_opening_angle_bracket_in_type_parameters);
2285            if (this.preferences.insert_space_after_opening_angle_bracket_in_type_parameters) {
2286                this.scribe.space();
2287            }
2288            for (int i = 0; i < typeParametersLength - 1; i++) {
2289                ((TypeParameter) typeParameters.get(i)).accept(this);
2290                this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_type_parameters);
2291                if (this.preferences.insert_space_after_comma_in_type_parameters) {
2292                    this.scribe.space();
2293                }
2294            }
2295            ((TypeParameter) typeParameters.get(typeParametersLength - 1)).accept(this);
2296            if (isClosingGenericToken()) {
2297                this.scribe.printNextToken(CLOSING_GENERICS_EXPECTEDTOKENS, this.preferences.insert_space_before_closing_angle_bracket_in_type_parameters);
2298            }
2299            if (this.preferences.insert_space_after_closing_angle_bracket_in_type_parameters) {
2300                this.scribe.space();
2301            }
2302        }
2303        
2304        final Type returnType = node.getReturnType2();
2305        if (returnType != null) {
2306            returnType.accept(this);
2307        }
2308        /*
2309         * Print the method name
2310         */

2311        this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, true);
2312
2313        boolean spaceBeforeParen = this.preferences.insert_space_before_opening_paren_in_method_declaration;
2314        if (node.isConstructor()) {
2315            spaceBeforeParen = this.preferences.insert_space_before_opening_paren_in_constructor_declaration;
2316        }
2317        this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, spaceBeforeParen);
2318        
2319        final List JavaDoc parameters = node.parameters();
2320        final int parametersLength = parameters.size();
2321        if (parametersLength != 0) {
2322            if (this.preferences.insert_space_after_opening_paren_in_method_declaration) {
2323                this.scribe.space();
2324            }
2325            Alignment2 parametersAlignment = this.scribe.createAlignment(
2326                    "methodParameters",//$NON-NLS-1$
2327
this.preferences.alignment_for_parameters_in_method_declaration,
2328                    parametersLength,
2329                    this.scribe.scanner.currentPosition);
2330            this.scribe.enterAlignment(parametersAlignment);
2331            boolean ok = false;
2332            do {
2333                try {
2334                    for (int i = 0; i < parametersLength; i++) {
2335                        if (i > 0) {
2336                            this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_method_declaration_parameters);
2337                            this.scribe.printTrailingComment();
2338                        }
2339                        this.scribe.alignFragment(parametersAlignment, i);
2340                        if (i > 0 && this.preferences.insert_space_after_comma_in_method_declaration_parameters) {
2341                            this.scribe.space();
2342                        }
2343                        ((SingleVariableDeclaration) parameters.get(i)).accept(this);
2344                    }
2345                    ok = true;
2346                } catch (AlignmentException e) {
2347                    this.scribe.redoAlignment(e);
2348                }
2349            } while (!ok);
2350            this.scribe.exitAlignment(parametersAlignment, true);
2351        
2352            this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_method_declaration);
2353        } else {
2354            this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_between_empty_parens_in_method_declaration);
2355        }
2356        /*
2357         * Check for extra dimensions
2358         */

2359        final int extraDimensions = node.getExtraDimensions();
2360        if (extraDimensions != 0) {
2361             for (int i = 0; i < extraDimensions; i++) {
2362                this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET);
2363                this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET);
2364             }
2365        }
2366                
2367        final List JavaDoc thrownExceptions = node.thrownExceptions();
2368        final int thrownExceptionsLength = thrownExceptions.size();
2369        if (thrownExceptionsLength != 0) {
2370            Alignment2 throwsAlignment = this.scribe.createAlignment(
2371                    "throws",//$NON-NLS-1$
2372
node.isConstructor()
2373                        ? this.preferences.alignment_for_throws_clause_in_constructor_declaration
2374                        : this.preferences.alignment_for_throws_clause_in_method_declaration,
2375                    thrownExceptionsLength, // throws is the first token
2376
this.scribe.scanner.currentPosition);
2377        
2378            this.scribe.enterAlignment(throwsAlignment);
2379            boolean ok = false;
2380            do {
2381                try {
2382                    this.scribe.alignFragment(throwsAlignment, 0);
2383                    this.scribe.printNextToken(TerminalTokens.TokenNamethrows, true);
2384        
2385                    for (int i = 0; i < thrownExceptionsLength; i++) {
2386                        if (i > 0) {
2387                            this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_method_declaration_throws);
2388                            this.scribe.printTrailingComment();
2389                            this.scribe.alignFragment(throwsAlignment, i);
2390                            if (this.preferences.insert_space_after_comma_in_method_declaration_throws) {
2391                                this.scribe.space();
2392                            }
2393                        } else {
2394                            this.scribe.space();
2395                        }
2396                        ((Name) thrownExceptions.get(i)).accept(this);
2397                    }
2398                    ok = true;
2399                } catch (AlignmentException e) {
2400                    this.scribe.redoAlignment(e);
2401                }
2402            } while (!ok);
2403            this.scribe.exitAlignment(throwsAlignment, true);
2404        }
2405
2406        final Block body = node.getBody();
2407        if (body != null) {
2408            /*
2409             * Method body
2410             */

2411            String JavaDoc method_declaration_brace = this.preferences.brace_position_for_method_declaration;
2412            formatLeftCurlyBrace(line, method_declaration_brace);
2413            formatOpeningBrace(method_declaration_brace, this.preferences.insert_space_before_opening_brace_in_method_declaration);
2414            final int numberOfBlankLinesAtBeginningOfMethodBody = this.preferences.blank_lines_at_beginning_of_method_body;
2415            if (numberOfBlankLinesAtBeginningOfMethodBody > 0) {
2416                this.scribe.printEmptyLines(numberOfBlankLinesAtBeginningOfMethodBody);
2417            }
2418            final List JavaDoc statements = body.statements();
2419            final int statementsLength = statements.size();
2420            if (statementsLength != 0) {
2421                this.scribe.printNewLine();
2422                if (this.preferences.indent_statements_compare_to_body) {
2423                    this.scribe.indent();
2424                }
2425                formatStatements(statements, true);
2426                this.scribe.printComment();
2427                if (this.preferences.indent_statements_compare_to_body) {
2428                    this.scribe.unIndent();
2429                }
2430            } else if (this.preferences.insert_new_line_in_empty_method_body) {
2431                this.scribe.printNewLine();
2432                if (this.preferences.indent_statements_compare_to_body) {
2433                    this.scribe.indent();
2434                }
2435                this.scribe.printComment();
2436                if (this.preferences.indent_statements_compare_to_body) {
2437                    this.scribe.unIndent();
2438                }
2439            }
2440            this.scribe.printNextToken(TerminalTokens.TokenNameRBRACE);
2441            this.scribe.printTrailingComment();
2442            if (method_declaration_brace.equals(DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED)) {
2443                this.scribe.unIndent();
2444            }
2445        } else {
2446            // no method body
2447
this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
2448            this.scribe.printTrailingComment();
2449        }
2450        return false;
2451    }
2452
2453    public boolean visit(MethodInvocation node) {
2454        MethodInvocationFragmentBuilder builder = new MethodInvocationFragmentBuilder();
2455        node.accept(builder);
2456        
2457        final List JavaDoc fragments = builder.fragments();
2458        final int fragmentsLength = fragments.size();
2459        if (fragmentsLength >= 3) {
2460            // manage cascading method invocations
2461
// check the first fragment
2462
final Expression firstFragment = (Expression) fragments.get(0);
2463            switch(firstFragment.getNodeType()) {
2464                case ASTNode.METHOD_INVOCATION :
2465                    formatSingleMethodInvocation((MethodInvocation) firstFragment);
2466                    break;
2467                default:
2468                    firstFragment.accept(this);
2469            }
2470            Alignment2 cascadingMessageSendAlignment =
2471                this.scribe.createAlignment(
2472                    "cascadingMessageSendAlignment", //$NON-NLS-1$
2473
this.preferences.alignment_for_selector_in_method_invocation,
2474                    Alignment.R_INNERMOST,
2475                    fragmentsLength,
2476                    this.scribe.scanner.currentPosition);
2477            this.scribe.enterAlignment(cascadingMessageSendAlignment);
2478            boolean ok = false;
2479            do {
2480                try {
2481                    this.scribe.alignFragment(cascadingMessageSendAlignment, 0);
2482                    this.scribe.printNextToken(TerminalTokens.TokenNameDOT);
2483                    for (int i = 1; i < fragmentsLength - 1; i++) {
2484                        MethodInvocation currentMethodInvocation = (MethodInvocation) fragments.get(i);
2485                        formatSingleMethodInvocation(currentMethodInvocation);
2486                        this.scribe.alignFragment(cascadingMessageSendAlignment, i);
2487                        this.scribe.printNextToken(TerminalTokens.TokenNameDOT);
2488                    }
2489                    MethodInvocation currentMethodInvocation = (MethodInvocation) fragments.get(fragmentsLength - 1);
2490                    formatSingleMethodInvocation(currentMethodInvocation);
2491                    ok = true;
2492                } catch(AlignmentException e){
2493                    this.scribe.redoAlignment(e);
2494                }
2495            } while (!ok);
2496            this.scribe.exitAlignment(cascadingMessageSendAlignment, true);
2497        } else {
2498            Expression expression = node.getExpression();
2499            if (expression != null) {
2500                expression.accept(this);
2501                this.scribe.printNextToken(TerminalTokens.TokenNameDOT);
2502            }
2503            formatSingleMethodInvocation(node);
2504        }
2505        return false;
2506    }
2507
2508    private void formatSingleMethodInvocation(MethodInvocation node) {
2509        final List JavaDoc typeArguments = node.typeArguments();
2510        final int typeArgumentsLength = typeArguments.size();
2511        if (typeArgumentsLength != 0) {
2512            this.scribe.printNextToken(TerminalTokens.TokenNameLESS, this.preferences.insert_space_before_opening_angle_bracket_in_type_arguments);
2513            if (this.preferences.insert_space_after_opening_angle_bracket_in_type_arguments) {
2514                this.scribe.space();
2515            }
2516            for (int i = 0; i < typeArgumentsLength - 1; i++) {
2517                ((Type) typeArguments.get(i)).accept(this);
2518                this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_type_arguments);
2519                if (this.preferences.insert_space_after_comma_in_type_arguments) {
2520                    this.scribe.space();
2521                }
2522            }
2523            ((Type) typeArguments.get(typeArgumentsLength - 1)).accept(this);
2524            if (isClosingGenericToken()) {
2525                this.scribe.printNextToken(CLOSING_GENERICS_EXPECTEDTOKENS, this.preferences.insert_space_before_closing_angle_bracket_in_type_arguments);
2526            }
2527            if (this.preferences.insert_space_after_closing_angle_bracket_in_type_arguments) {
2528                this.scribe.space();
2529            }
2530        }
2531        this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier); // selector
2532
this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_method_invocation);
2533
2534        final List JavaDoc arguments = node.arguments();
2535        final int argumentsLength = arguments.size();
2536        if (argumentsLength != 0) {
2537            if (this.preferences.insert_space_after_opening_paren_in_method_invocation) {
2538                this.scribe.space();
2539            }
2540            if (argumentsLength > 1) {
2541                Alignment2 argumentsAlignment = this.scribe.createAlignment(
2542                        "messageArguments", //$NON-NLS-1$
2543
this.preferences.alignment_for_arguments_in_method_invocation,
2544                        argumentsLength,
2545                        this.scribe.scanner.currentPosition);
2546                this.scribe.enterAlignment(argumentsAlignment);
2547                boolean ok = false;
2548                do {
2549                    try {
2550                        for (int i = 0; i < argumentsLength; i++) {
2551                            if (i > 0) {
2552                                this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_method_invocation_arguments);
2553                                this.scribe.printTrailingComment();
2554                            }
2555                            this.scribe.alignFragment(argumentsAlignment, i);
2556                            if (i > 0 && this.preferences.insert_space_after_comma_in_method_invocation_arguments) {
2557                                this.scribe.space();
2558                            }
2559                            ((Expression) arguments.get(i)).accept(this);
2560                        }
2561                        ok = true;
2562                    } catch (AlignmentException e) {
2563                        this.scribe.redoAlignment(e);
2564                    }
2565                } while (!ok);
2566                this.scribe.exitAlignment(argumentsAlignment, true);
2567            } else {
2568                for (int i = 0; i < argumentsLength; i++) {
2569                    if (i > 0) {
2570                        this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_method_invocation_arguments);
2571                        this.scribe.printTrailingComment();
2572                    }
2573                    if (i > 0 && this.preferences.insert_space_after_comma_in_method_invocation_arguments) {
2574                        this.scribe.space();
2575                    }
2576                    ((Expression) arguments.get(i)).accept(this);
2577                }
2578            }
2579            this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_method_invocation);
2580        } else {
2581            this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_between_empty_parens_in_method_invocation);
2582        }
2583    }
2584    
2585    public boolean visit(NormalAnnotation node) {
2586        this.scribe.printNextToken(TerminalTokens.TokenNameAT);
2587        if (this.preferences.insert_space_after_at_in_annotation) {
2588            this.scribe.space();
2589        }
2590        node.getTypeName().accept(this);
2591        this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_annotation);
2592        if (this.preferences.insert_space_after_opening_paren_in_annotation) {
2593            this.scribe.space();
2594        }
2595        final List JavaDoc memberValuePairs = node.values();
2596        final int memberValuePairsLength = memberValuePairs.size();
2597        if (memberValuePairs.size() != 0) {
2598            for (int i = 0; i < memberValuePairsLength - 1; i++) {
2599                ((MemberValuePair) memberValuePairs.get(i)).accept(this);
2600                this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_annotation);
2601                if (this.preferences.insert_space_after_comma_in_annotation) {
2602                    this.scribe.space();
2603                }
2604            }
2605            ((MemberValuePair) memberValuePairs.get(memberValuePairsLength - 1)).accept(this);
2606        }
2607        this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_annotation);
2608        return false;
2609    }
2610
2611    public boolean visit(NullLiteral node) {
2612        this.scribe.printNextToken(TerminalTokens.TokenNamenull);
2613        return false;
2614    }
2615
2616    public boolean visit(NumberLiteral node) {
2617        if (isNextToken(TerminalTokens.TokenNameMINUS)) {
2618            this.scribe.printNextToken(TerminalTokens.TokenNameMINUS, this.preferences.insert_space_before_unary_operator);
2619            if (this.preferences.insert_space_after_unary_operator) {
2620                this.scribe.space();
2621            }
2622        }
2623        this.scribe.printNextToken(NUMBER_LITERALS_EXPECTEDTOKENS);
2624        return false;
2625    }
2626
2627    public boolean visit(ParameterizedType node) {
2628        node.getType().accept(this);
2629        this.scribe.printNextToken(TerminalTokens.TokenNameLESS, this.preferences.insert_space_before_opening_angle_bracket_in_parameterized_type_reference);
2630        if (this.preferences.insert_space_after_opening_angle_bracket_in_parameterized_type_reference) {
2631            this.scribe.space();
2632        }
2633        final List JavaDoc typeArguments = node.typeArguments();
2634        final int typeArgumentsLength = typeArguments.size();
2635        for (int i = 0; i < typeArgumentsLength - 1; i++) {
2636            ((Type) typeArguments.get(i)).accept(this);
2637            this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_parameterized_type_reference);
2638            if (this.preferences.insert_space_after_comma_in_parameterized_type_reference) {
2639                this.scribe.space();
2640            }
2641        }
2642        ((Type) typeArguments.get(typeArgumentsLength - 1)).accept(this);
2643        if (isClosingGenericToken()) {
2644            this.scribe.printNextToken(CLOSING_GENERICS_EXPECTEDTOKENS, this.preferences.insert_space_before_closing_angle_bracket_in_parameterized_type_reference);
2645        }
2646        return false;
2647    }
2648
2649    public boolean visit(ParenthesizedExpression node) {
2650        this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_parenthesized_expression);
2651        if (this.preferences.insert_space_after_opening_paren_in_parenthesized_expression) {
2652            this.scribe.space();
2653        }
2654        node.getExpression().accept(this);
2655        this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_parenthesized_expression);
2656        return false;
2657    }
2658
2659    public boolean visit(PostfixExpression node) {
2660        node.getOperand().accept(this);
2661        int operator = node.getOperator() == PostfixExpression.Operator.INCREMENT
2662            ? TerminalTokens.TokenNamePLUS_PLUS : TerminalTokens.TokenNameMINUS_MINUS;
2663        this.scribe.printNextToken(operator, this.preferences.insert_space_before_postfix_operator);
2664        if (this.preferences.insert_space_after_postfix_operator) {
2665            this.scribe.space();
2666        }
2667        return false;
2668    }
2669
2670    public boolean visit(PrefixExpression node) {
2671        int operator;
2672        boolean insertSpaceBeforeOperator;
2673        boolean insertSpaceAfterOperator;
2674        final Operator operator2 = node.getOperator();
2675        if (operator2 == PrefixExpression.Operator.INCREMENT) {
2676            operator = TerminalTokens.TokenNamePLUS_PLUS;
2677            insertSpaceBeforeOperator = this.preferences.insert_space_before_prefix_operator;
2678            insertSpaceAfterOperator = this.preferences.insert_space_after_prefix_operator;
2679        } else if (operator2 == PrefixExpression.Operator.DECREMENT) {
2680            operator = TerminalTokens.TokenNameMINUS_MINUS;
2681            insertSpaceBeforeOperator = this.preferences.insert_space_before_prefix_operator;
2682            insertSpaceAfterOperator = this.preferences.insert_space_after_prefix_operator;
2683        } else if (operator2 == PrefixExpression.Operator.COMPLEMENT) {
2684            operator = TerminalTokens.TokenNameTWIDDLE;
2685            insertSpaceBeforeOperator = this.preferences.insert_space_before_unary_operator;
2686            insertSpaceAfterOperator = this.preferences.insert_space_after_unary_operator;
2687        } else if (operator2 == PrefixExpression.Operator.MINUS) {
2688            operator = TerminalTokens.TokenNameMINUS;
2689            insertSpaceBeforeOperator = this.preferences.insert_space_before_unary_operator;
2690            insertSpaceAfterOperator = this.preferences.insert_space_after_unary_operator;
2691        } else if (operator2 == PrefixExpression.Operator.NOT) {
2692            operator = TerminalTokens.TokenNameNOT;
2693            insertSpaceBeforeOperator = this.preferences.insert_space_before_unary_operator;
2694            insertSpaceAfterOperator = this.preferences.insert_space_after_unary_operator;
2695        } else {
2696            operator = TerminalTokens.TokenNamePLUS;
2697            insertSpaceBeforeOperator = this.preferences.insert_space_before_unary_operator;
2698            insertSpaceAfterOperator = this.preferences.insert_space_after_unary_operator;
2699        }
2700
2701        this.scribe.printNextToken(operator, insertSpaceBeforeOperator);
2702        if (insertSpaceAfterOperator) {
2703            this.scribe.space();
2704        }
2705        node.getOperand().accept(this);
2706        return false;
2707    }
2708
2709    public boolean visit(PrimitiveType node) {
2710        this.scribe.printNextToken(PRIMITIVE_TYPE_EXPECTEDTOKENS);
2711        return false;
2712    }
2713
2714    public boolean visit(QualifiedName node) {
2715        node.getQualifier().accept(this);
2716        this.scribe.printNextToken(TerminalTokens.TokenNameDOT);
2717        node.getName().accept(this);
2718        return false;
2719    }
2720
2721    public boolean visit(QualifiedType node) {
2722        node.getQualifier().accept(this);
2723        this.scribe.printNextToken(TerminalTokens.TokenNameDOT);
2724        node.getName().accept(this);
2725        return false;
2726    }
2727
2728    public boolean visit(ReturnStatement node) {
2729        this.scribe.printNextToken(TerminalTokens.TokenNamereturn);
2730        final Expression expression = node.getExpression();
2731        if (expression != null) {
2732            switch(expression.getNodeType()) {
2733                case ASTNode.PARENTHESIZED_EXPRESSION :
2734                    if (this.preferences.insert_space_before_parenthesized_expression_in_return) {
2735                        this.scribe.space();
2736                    }
2737                    break;
2738                default:
2739                    this.scribe.space();
2740            }
2741            expression.accept(this);
2742        }
2743        this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
2744        this.scribe.printTrailingComment();
2745        return false;
2746    }
2747
2748    public boolean visit(SimpleName node) {
2749        this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier);
2750        return false;
2751    }
2752
2753    public boolean visit(SimpleType node) {
2754        node.getName().accept(this);
2755        return false;
2756    }
2757
2758    public boolean visit(SingleMemberAnnotation node) {
2759        this.scribe.printNextToken(TerminalTokens.TokenNameAT);
2760        if (this.preferences.insert_space_after_at_in_annotation) {
2761            this.scribe.space();
2762        }
2763        node.getTypeName().accept(this);
2764        this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_annotation);
2765        if (this.preferences.insert_space_after_opening_paren_in_annotation) {
2766            this.scribe.space();
2767        }
2768        node.getValue().accept(this);
2769        this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_annotation);
2770        return false;
2771    }
2772
2773    public boolean visit(SingleVariableDeclaration node) {
2774        final List JavaDoc modifiers = node.modifiers();
2775        if (modifiers.size() != 0) {
2776            this.scribe.printModifiers(modifiers, this);
2777            this.scribe.space();
2778        }
2779
2780        node.getType().accept(this);
2781        
2782        if (node.isVarargs()) {
2783            this.scribe.printNextToken(TerminalTokens.TokenNameELLIPSIS, this.preferences.insert_space_before_ellipsis);
2784            if (this.preferences.insert_space_after_ellipsis) {
2785                this.scribe.space();
2786            }
2787            this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, false);
2788        } else {
2789            /*
2790             * Print the argument name
2791             */

2792            this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, true);
2793        }
2794        
2795        final int extraDimensions = node.getExtraDimensions();
2796        if (extraDimensions != 0) {
2797            for (int i = 0; i < extraDimensions; i++) {
2798                this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET);
2799                this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET);
2800            }
2801        }
2802        final Expression initialization = node.getInitializer();
2803        if (initialization != null) {
2804            this.scribe.printNextToken(TerminalTokens.TokenNameEQUAL, this.preferences.insert_space_before_assignment_operator);
2805            if (this.preferences.insert_space_after_assignment_operator) {
2806                this.scribe.space();
2807            }
2808            Alignment2 assignmentAlignment = this.scribe.createAlignment("localDeclarationAssignmentAlignment", this.preferences.alignment_for_assignment, 1, this.scribe.scanner.currentPosition); //$NON-NLS-1$
2809
this.scribe.enterAlignment(assignmentAlignment);
2810            boolean ok = false;
2811            do {
2812                try {
2813                    this.scribe.alignFragment(assignmentAlignment, 0);
2814                    initialization.accept(this);
2815                    ok = true;
2816                } catch(AlignmentException e){
2817                    this.scribe.redoAlignment(e);
2818                }
2819            } while (!ok);
2820            this.scribe.exitAlignment(assignmentAlignment, true);
2821        }
2822        return false;
2823    }
2824
2825    public boolean visit(StringLiteral node) {
2826        this.scribe.checkNLSTag(node.getStartPosition());
2827        this.scribe.printNextToken(TerminalTokens.TokenNameStringLiteral);
2828        this.scribe.printTrailingComment();
2829        return false;
2830    }
2831
2832    public boolean visit(SuperConstructorInvocation node) {
2833        final Expression qualification = node.getExpression();
2834        if (qualification != null) {
2835            qualification.accept(this);
2836            this.scribe.printNextToken(TerminalTokens.TokenNameDOT);
2837        }
2838        final List JavaDoc typeArguments = node.typeArguments();
2839        final int typeArgumentsLength = typeArguments.size();
2840        if (typeArgumentsLength != 0) {
2841                this.scribe.printNextToken(TerminalTokens.TokenNameLESS, this.preferences.insert_space_before_opening_angle_bracket_in_type_arguments);
2842                if (this.preferences.insert_space_after_opening_angle_bracket_in_type_arguments) {
2843                    this.scribe.space();
2844                }
2845                for (int i = 0; i < typeArgumentsLength - 1; i++) {
2846                    ((Type) typeArguments.get(i)).accept(this);
2847                    this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_type_arguments);
2848                    if (this.preferences.insert_space_after_comma_in_type_arguments) {
2849                        this.scribe.space();
2850                    }
2851                }
2852                ((Type) typeArguments.get(typeArgumentsLength - 1)).accept(this);
2853                if (isClosingGenericToken()) {
2854                    this.scribe.printNextToken(CLOSING_GENERICS_EXPECTEDTOKENS, this.preferences.insert_space_before_closing_angle_bracket_in_type_arguments);
2855                }
2856                if (this.preferences.insert_space_after_closing_angle_bracket_in_type_arguments) {
2857                    this.scribe.space();
2858                }
2859        }
2860        
2861        this.scribe.printNextToken(TerminalTokens.TokenNamesuper);
2862        this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_method_invocation);
2863        
2864        final List JavaDoc arguments = node.arguments();
2865        final int argumentsLength = arguments.size();
2866        if (argumentsLength != 0) {
2867            if (this.preferences.insert_space_after_opening_paren_in_method_invocation) {
2868                this.scribe.space();
2869            }
2870            Alignment2 argumentsAlignment =this.scribe.createAlignment(
2871                    "explicit_constructor_call",//$NON-NLS-1$
2872
this.preferences.alignment_for_arguments_in_explicit_constructor_call,
2873                    argumentsLength,
2874                    this.scribe.scanner.currentPosition);
2875            this.scribe.enterAlignment(argumentsAlignment);
2876            boolean ok = false;
2877            do {
2878                try {
2879                    for (int i = 0; i < argumentsLength; i++) {
2880                        if (i > 0) {
2881                            this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_explicit_constructor_call_arguments);
2882                            this.scribe.printTrailingComment();
2883                        }
2884                        this.scribe.alignFragment(argumentsAlignment, i);
2885                        if (i > 0 && this.preferences.insert_space_after_comma_in_explicit_constructor_call_arguments) {
2886                            this.scribe.space();
2887                        }
2888                        ((Expression) arguments.get(i)).accept(this);
2889                    }
2890                    ok = true;
2891                } catch (AlignmentException e) {
2892                    this.scribe.redoAlignment(e);
2893                }
2894            } while (!ok);
2895            this.scribe.exitAlignment(argumentsAlignment, true);
2896            this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_method_invocation);
2897        } else {
2898            this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_between_empty_parens_in_method_invocation);
2899        }
2900        this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
2901        this.scribe.printTrailingComment();
2902        return false;
2903    }
2904
2905    public boolean visit(SuperFieldAccess node) {
2906        final Name qualifier = node.getQualifier();
2907        if (qualifier != null) {
2908            qualifier.accept(this);
2909            this.scribe.printNextToken(TerminalTokens.TokenNameDOT);
2910        }
2911        this.scribe.printNextToken(TerminalTokens.TokenNamesuper);
2912        this.scribe.printNextToken(TerminalTokens.TokenNameDOT);
2913        this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier);
2914        return false;
2915    }
2916
2917    public boolean visit(SuperMethodInvocation node) {
2918        final Name qualifier = node.getQualifier();
2919        if (qualifier != null) {
2920            qualifier.accept(this);
2921            this.scribe.printNextToken(TerminalTokens.TokenNameDOT);
2922        }
2923        this.scribe.printNextToken(TerminalTokens.TokenNamesuper);
2924        this.scribe.printNextToken(TerminalTokens.TokenNameDOT);
2925        this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier);
2926        this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_method_invocation);
2927
2928        final List JavaDoc arguments = node.arguments();
2929        final int argumentsLength = arguments.size();
2930        if (argumentsLength != 0) {
2931            if (this.preferences.insert_space_after_opening_paren_in_method_invocation) {
2932                this.scribe.space();
2933            }
2934            if (argumentsLength > 1) {
2935                Alignment2 argumentsAlignment = this.scribe.createAlignment(
2936                        "messageArguments", //$NON-NLS-1$
2937
this.preferences.alignment_for_arguments_in_method_invocation,
2938                        argumentsLength,
2939                        this.scribe.scanner.currentPosition);
2940                this.scribe.enterAlignment(argumentsAlignment);
2941                boolean ok = false;
2942                do {
2943                    try {
2944                        for (int i = 0; i < argumentsLength; i++) {
2945                            if (i > 0) {
2946                                this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_method_invocation_arguments);
2947                                this.scribe.printTrailingComment();
2948                            }
2949                            this.scribe.alignFragment(argumentsAlignment, i);
2950                            if (i > 0 && this.preferences.insert_space_after_comma_in_method_invocation_arguments) {
2951                                this.scribe.space();
2952                            }
2953                            ((Expression) arguments.get(i)).accept(this);
2954                        }
2955                        ok = true;
2956                    } catch (AlignmentException e) {
2957                        this.scribe.redoAlignment(e);
2958                    }
2959                } while (!ok);
2960                this.scribe.exitAlignment(argumentsAlignment, true);
2961            } else {
2962                for (int i = 0; i < argumentsLength; i++) {
2963                    if (i > 0) {
2964                        this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_method_invocation_arguments);
2965                        this.scribe.printTrailingComment();
2966                    }
2967                    if (i > 0 && this.preferences.insert_space_after_comma_in_method_invocation_arguments) {
2968                        this.scribe.space();
2969                    }
2970                    ((Expression) arguments.get(i)).accept(this);
2971                }
2972            }
2973            this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_method_invocation);
2974        } else {
2975            this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_between_empty_parens_in_method_invocation);
2976        }
2977        return false;
2978    }
2979
2980    public boolean visit(SwitchCase node) {
2981        Expression constant = node.getExpression();
2982        if (constant == null) {
2983            this.scribe.printNextToken(TerminalTokens.TokenNamedefault);
2984            this.scribe.printNextToken(TerminalTokens.TokenNameCOLON, this.preferences.insert_space_before_colon_in_default);
2985        } else {
2986            this.scribe.printNextToken(TerminalTokens.TokenNamecase);
2987            this.scribe.space();
2988            constant.accept(this);
2989            this.scribe.printNextToken(TerminalTokens.TokenNameCOLON, this.preferences.insert_space_before_colon_in_case);
2990        }
2991        return false;
2992    }
2993
2994    public boolean visit(SwitchStatement node) {
2995        this.scribe.printNextToken(TerminalTokens.TokenNameswitch);
2996        this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_switch);
2997        
2998        if (this.preferences.insert_space_after_opening_paren_in_switch) {
2999            this.scribe.space();
3000        }
3001        
3002        node.getExpression().accept(this);
3003        this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_switch);
3004        /*
3005         * Type body
3006         */

3007        String JavaDoc switch_brace = this.preferences.brace_position_for_switch;
3008        formatOpeningBrace(switch_brace, this.preferences.insert_space_before_opening_brace_in_switch);
3009        this.scribe.printNewLine();
3010
3011        if (this.preferences.indent_switchstatements_compare_to_switch) {
3012            this.scribe.indent();
3013        }
3014        final List JavaDoc statements = node.statements();
3015        final int statementsLength = statements.size();
3016        boolean wasACase = false;
3017        boolean wasAStatement = false;
3018        if (statementsLength != 0) {
3019            for (int i = 0; i < statementsLength; i++) {
3020                final Statement statement = (Statement) statements.get(i);
3021                if (statement instanceof SwitchCase) {
3022                    if (wasACase) {
3023                        this.scribe.printNewLine();
3024                    }
3025                    if ((wasACase && this.preferences.indent_switchstatements_compare_to_cases)
3026                        || (wasAStatement && this.preferences.indent_switchstatements_compare_to_cases)) {
3027                        this.scribe.unIndent();
3028                    }
3029                    statement.accept(this);
3030                    this.scribe.printTrailingComment();
3031                    wasACase = true;
3032                    wasAStatement = false;
3033                    if (this.preferences.indent_switchstatements_compare_to_cases) {
3034                        this.scribe.indent();
3035                    }
3036                } else if (statement instanceof BreakStatement) {
3037                    if (this.preferences.indent_breaks_compare_to_cases) {
3038                        if (wasAStatement && !this.preferences.indent_switchstatements_compare_to_cases) {
3039                            this.scribe.indent();
3040                        }
3041                    } else {
3042                        if (wasAStatement) {
3043                            if (this.preferences.indent_switchstatements_compare_to_cases) {
3044                                this.scribe.unIndent();
3045                            }
3046                        }
3047                        if (wasACase && this.preferences.indent_switchstatements_compare_to_cases) {
3048                            this.scribe.unIndent();
3049                        }
3050                    }
3051                    if (wasACase) {
3052                        this.scribe.printNewLine();
3053                    }
3054                    statement.accept(this);
3055                    if (this.preferences.indent_breaks_compare_to_cases) {
3056                        this.scribe.unIndent();
3057                    }
3058                    wasACase = false;
3059                    wasAStatement = false;
3060                } else if (statement instanceof Block) {
3061                    String JavaDoc bracePosition;
3062                    if (wasACase) {
3063                        if (this.preferences.indent_switchstatements_compare_to_cases) {
3064                            this.scribe.unIndent();
3065                        }
3066                        bracePosition = this.preferences.brace_position_for_block_in_case;
3067                        formatBlock((Block) statement, bracePosition, this.preferences.insert_space_after_colon_in_case);
3068                        if (this.preferences.indent_switchstatements_compare_to_cases) {
3069                            this.scribe.indent();
3070                        }
3071                    } else {
3072                        bracePosition = this.preferences.brace_position_for_block;
3073                        formatBlock((Block) statement, bracePosition, this.preferences.insert_space_before_opening_brace_in_block);
3074                    }
3075                    wasAStatement = true;
3076                    wasACase = false;
3077                } else {
3078                    this.scribe.printNewLine();
3079                    statement.accept(this);
3080                    wasAStatement = true;
3081                    wasACase = false;
3082                }
3083                if (!wasACase) {
3084                    this.scribe.printNewLine();
3085                }
3086                this.scribe.printComment();
3087            }
3088        }
3089        
3090        if ((wasACase || wasAStatement) && this.preferences.indent_switchstatements_compare_to_cases) {
3091            this.scribe.unIndent();
3092        }
3093        if (this.preferences.indent_switchstatements_compare_to_switch) {
3094            this.scribe.unIndent();
3095        }
3096        this.scribe.printNewLine();
3097        this.scribe.printNextToken(TerminalTokens.TokenNameRBRACE);
3098        this.scribe.printTrailingComment();
3099        if (switch_brace.equals(DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED)) {
3100            this.scribe.unIndent();
3101        }
3102        return false;
3103    }
3104
3105    public boolean visit(SynchronizedStatement node) {
3106        this.scribe.printNextToken(TerminalTokens.TokenNamesynchronized);
3107
3108        final int line = this.scribe.line;
3109
3110        this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_synchronized);
3111        
3112        if (this.preferences.insert_space_after_opening_paren_in_synchronized) {
3113            this.scribe.space();
3114        }
3115        node.getExpression().accept(this);
3116    
3117        this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_synchronized);
3118        
3119        formatLeftCurlyBrace(line, this.preferences.brace_position_for_block);
3120        node.getBody().accept(this);
3121        return false;
3122    }
3123
3124    public boolean visit(ThisExpression node) {
3125        final Name qualifier = node.getQualifier();
3126        if (qualifier != null) {
3127            qualifier.accept(this);
3128            this.scribe.printNextToken(TerminalTokens.TokenNameDOT);
3129        }
3130        this.scribe.printNextToken(TerminalTokens.TokenNamethis);
3131        return false;
3132    }
3133
3134    public boolean visit(ThrowStatement node) {
3135        this.scribe.printNextToken(TerminalTokens.TokenNamethrow);
3136        this.scribe.space();
3137        node.getExpression().accept(this);
3138        this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
3139        this.scribe.printTrailingComment();
3140        return false;
3141    }
3142
3143    public boolean visit(TryStatement node) {
3144
3145        this.scribe.printNextToken(TerminalTokens.TokenNametry);
3146        node.getBody().accept(this);
3147        final List JavaDoc catchClauses = node.catchClauses();
3148        final int catchClausesLength = catchClauses.size();
3149        if (catchClausesLength != 0) {
3150            for (int i = 0; i < catchClausesLength; i++) {
3151                if (this.preferences.insert_new_line_before_catch_in_try_statement) {
3152                    this.scribe.printNewLine();
3153                }
3154                this.scribe.printNextToken(TerminalTokens.TokenNamecatch, this.preferences.insert_space_after_closing_brace_in_block);
3155                final int line = this.scribe.line;
3156                this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_catch);
3157                
3158                if (this.preferences.insert_space_after_opening_paren_in_catch) {
3159                    this.scribe.space();
3160                }
3161                
3162                final CatchClause catchClause = ((CatchClause) catchClauses.get(i));
3163                catchClause.getException().accept(this);
3164            
3165                this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_catch);
3166                
3167                formatLeftCurlyBrace(line, this.preferences.brace_position_for_block);
3168                catchClause.getBody().accept(this);
3169            }
3170        }
3171        final Block finallyBlock = node.getFinally();
3172        if (finallyBlock != null) {
3173            if (this.preferences.insert_new_line_before_finally_in_try_statement) {
3174                this.scribe.printNewLine();
3175            }
3176            this.scribe.printNextToken(TerminalTokens.TokenNamefinally, this.preferences.insert_space_after_closing_brace_in_block);
3177            finallyBlock.accept(this);
3178        }
3179        return false;
3180    }
3181
3182    public boolean visit(TypeDeclaration node) {
3183        /*
3184         * Print comments to get proper line number
3185         */

3186        this.scribe.printComment();
3187        final int line = this.scribe.line;
3188        
3189        final List JavaDoc modifiers = node.modifiers();
3190        if (modifiers.size() != 0) {
3191            this.scribe.printModifiers(modifiers, this);
3192            this.scribe.space();
3193        }
3194        final boolean isInterface = node.isInterface();
3195        if (isInterface) {
3196            this.scribe.printNextToken(TerminalTokens.TokenNameinterface, true);
3197        } else {
3198            this.scribe.printNextToken(TerminalTokens.TokenNameclass, true);
3199        }
3200
3201        this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, true);
3202
3203        final List JavaDoc typeParameters = node.typeParameters();
3204        final int typeParametersLength = typeParameters.size();
3205        if (typeParametersLength != 0) {
3206            this.scribe.printNextToken(TerminalTokens.TokenNameLESS, this.preferences.insert_space_before_opening_angle_bracket_in_type_parameters);
3207            if (this.preferences.insert_space_after_opening_angle_bracket_in_type_parameters) {
3208                this.scribe.space();
3209            }
3210            for (int i = 0; i < typeParametersLength - 1; i++) {
3211                ((TypeParameter) typeParameters.get(i)).accept(this);
3212                this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_type_parameters);
3213                if (this.preferences.insert_space_after_comma_in_type_parameters) {
3214                    this.scribe.space();
3215                }
3216            }
3217            ((TypeParameter) typeParameters.get(typeParametersLength - 1)).accept(this);
3218            if (isClosingGenericToken()) {
3219                this.scribe.printNextToken(CLOSING_GENERICS_EXPECTEDTOKENS, this.preferences.insert_space_before_closing_angle_bracket_in_type_parameters);
3220            }
3221            if (this.preferences.insert_space_after_closing_angle_bracket_in_type_parameters) {
3222                this.scribe.space();
3223            }
3224        }
3225        /*
3226         * Superclass
3227         */

3228        final Type superclass = node.getSuperclassType();
3229        if (superclass != null) {
3230            Alignment2 superclassAlignment =this.scribe.createAlignment(
3231                    "superclass", //$NON-NLS-1$
3232
this.preferences.alignment_for_superclass_in_type_declaration,
3233                    2,
3234                    this.scribe.scanner.currentPosition);
3235            this.scribe.enterAlignment(superclassAlignment);
3236            boolean ok = false;
3237            do {
3238                try {
3239                    this.scribe.alignFragment(superclassAlignment, 0);
3240                    this.scribe.printNextToken(TerminalTokens.TokenNameextends, true);
3241                    this.scribe.alignFragment(superclassAlignment, 1);
3242                    this.scribe.space();
3243                    superclass.accept(this);
3244                    ok = true;
3245                } catch (AlignmentException e) {
3246                    this.scribe.redoAlignment(e);
3247                }
3248            } while (!ok);
3249            this.scribe.exitAlignment(superclassAlignment, true);
3250        }
3251
3252        /*
3253         * Super Interfaces
3254         */

3255        final List JavaDoc superInterfaces = node.superInterfaceTypes();
3256        final int superInterfacesLength = superInterfaces.size();
3257        if (superInterfacesLength != 0) {
3258            Alignment2 interfaceAlignment = this.scribe.createAlignment(
3259                    "superInterfaces",//$NON-NLS-1$
3260
this.preferences.alignment_for_superinterfaces_in_type_declaration,
3261                    superInterfacesLength+1, // implements token is first fragment
3262
this.scribe.scanner.currentPosition);
3263            this.scribe.enterAlignment(interfaceAlignment);
3264            boolean ok = false;
3265            do {
3266                try {
3267                    this.scribe.alignFragment(interfaceAlignment, 0);
3268                    if (isInterface) {
3269                        this.scribe.printNextToken(TerminalTokens.TokenNameextends, true);
3270                    } else {
3271                        this.scribe.printNextToken(TerminalTokens.TokenNameimplements, true);
3272                    }
3273                    this.scribe.alignFragment(interfaceAlignment, 1);
3274                    this.scribe.space();
3275                    ((Type) superInterfaces.get(0)).accept(this);
3276                    for (int i = 1; i < superInterfacesLength; i++) {
3277                        this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_superinterfaces);
3278                        this.scribe.printTrailingComment();
3279                        this.scribe.alignFragment(interfaceAlignment, i+1);
3280                        if (this.preferences.insert_space_after_comma_in_superinterfaces) {
3281                            this.scribe.space();
3282                        }
3283                        ((Type) superInterfaces.get(i)).accept(this);
3284                    }
3285                    ok = true;
3286                } catch (AlignmentException e) {
3287                    this.scribe.redoAlignment(e);
3288                }
3289            } while (!ok);
3290            this.scribe.exitAlignment(interfaceAlignment, true);
3291        }
3292
3293        final String JavaDoc class_declaration_brace = this.preferences.brace_position_for_type_declaration;
3294        final boolean space_before_opening_brace = this.preferences.insert_space_before_opening_brace_in_type_declaration;
3295
3296        formatLeftCurlyBrace(line, class_declaration_brace);
3297        final List JavaDoc bodyDeclarations = node.bodyDeclarations();
3298        formatTypeOpeningBrace(class_declaration_brace, space_before_opening_brace, bodyDeclarations.size() != 0, node);
3299        
3300        final boolean indent_body_declarations_compare_to_header = this.preferences.indent_body_declarations_compare_to_type_header;
3301
3302        if (indent_body_declarations_compare_to_header) {
3303            this.scribe.indent();
3304        }
3305        
3306        formatTypeMembers(bodyDeclarations, true);
3307        
3308        if (indent_body_declarations_compare_to_header) {
3309            this.scribe.unIndent();
3310        }
3311
3312        if (this.preferences.insert_new_line_in_empty_type_declaration) {
3313            this.scribe.printNewLine();
3314        }
3315        this.scribe.printNextToken(TerminalTokens.TokenNameRBRACE);
3316        this.scribe.printTrailingComment();
3317        if (class_declaration_brace.equals(DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED)) {
3318            this.scribe.unIndent();
3319        }
3320        if (hasComments()) {
3321            this.scribe.printNewLine();
3322        }
3323        return false;
3324    }
3325
3326    public boolean visit(TypeDeclarationStatement node) {
3327        node.getDeclaration().accept(this);
3328        return false;
3329    }
3330
3331    public boolean visit(TypeLiteral node) {
3332        node.getType().accept(this);
3333        this.scribe.printNextToken(TerminalTokens.TokenNameDOT);
3334        this.scribe.printNextToken(TerminalTokens.TokenNameclass);
3335        return false;
3336    }
3337
3338    public boolean visit(TypeParameter node) {
3339        node.getName().accept(this);
3340        final List JavaDoc bounds = node.typeBounds();
3341        final int boundsLength = bounds.size();
3342        if (boundsLength != 0) {
3343            this.scribe.printNextToken(TerminalTokens.TokenNameextends, true);
3344            this.scribe.space();
3345            ((Type) bounds.get(0)).accept(this);
3346            if (boundsLength > 1) {
3347                this.scribe.printNextToken(TerminalTokens.TokenNameAND, this.preferences.insert_space_before_and_in_type_parameter);
3348                if (this.preferences.insert_space_after_and_in_type_parameter) {
3349                    this.scribe.space();
3350                }
3351                for (int i = 1; i < boundsLength - 1; i++) {
3352                    ((Type) bounds.get(i)).accept(this);
3353                    this.scribe.printNextToken(TerminalTokens.TokenNameAND, this.preferences.insert_space_before_and_in_type_parameter);
3354                    if (this.preferences.insert_space_after_and_in_type_parameter) {
3355                        this.scribe.space();
3356                    }
3357                }
3358                ((Type) bounds.get(boundsLength - 1)).accept(this);
3359            }
3360        }
3361        return false;
3362    }
3363
3364    public boolean visit(VariableDeclarationExpression node) {
3365        formatLocalDeclaration(node, this.preferences.insert_space_before_comma_in_multiple_local_declarations, this.preferences.insert_space_after_comma_in_multiple_local_declarations);
3366        return false;
3367    }
3368
3369    public boolean visit(VariableDeclarationStatement node) {
3370        final List JavaDoc modifiers = node.modifiers();
3371        if (modifiers.size() != 0) {
3372            this.scribe.printModifiers(modifiers, this);
3373            this.scribe.space();
3374        }
3375
3376        node.getType().accept(this);
3377        
3378        formatVariableDeclarationFragments(node.fragments(), this.preferences.insert_space_before_comma_in_multiple_local_declarations, this.preferences.insert_space_after_comma_in_multiple_local_declarations);
3379        this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
3380        this.scribe.printTrailingComment();
3381        return false;
3382    }
3383
3384    public boolean visit(WhileStatement node) {
3385        this.scribe.printNextToken(TerminalTokens.TokenNamewhile);
3386        final int line = this.scribe.line;
3387        this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_while);
3388        
3389        if (this.preferences.insert_space_after_opening_paren_in_while) {
3390            this.scribe.space();
3391        }
3392        node.getExpression().accept(this);
3393        
3394        this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_while);
3395        
3396        formatAction(line, node.getBody(),false);
3397        return false;
3398    }
3399
3400    public boolean visit(WildcardType node) {
3401        this.scribe.printNextToken(TerminalTokens.TokenNameQUESTION, this.preferences.insert_space_before_question_in_wilcard);
3402        final Type bound = node.getBound();
3403        if (bound != null) {
3404            if (node.isUpperBound()) {
3405                this.scribe.printNextToken(TerminalTokens.TokenNameextends, true);
3406            } else {
3407                this.scribe.printNextToken(TerminalTokens.TokenNamesuper, true);
3408            }
3409            this.scribe.space();
3410            bound.accept(this);
3411        } else if (this.preferences.insert_space_after_question_in_wilcard) {
3412            this.scribe.space();
3413        }
3414        return false;
3415    }
3416    
3417}
3418
Popular Tags