KickJava   Java API By Example, From Geeks To Geeks.

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


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

11 package org.eclipse.jdt.internal.formatter;
12
13 import java.util.ArrayList JavaDoc;
14 import java.util.Map JavaDoc;
15
16 import org.eclipse.jdt.core.JavaCore;
17 import org.eclipse.jdt.core.compiler.IProblem;
18 import org.eclipse.jdt.core.compiler.InvalidInputException;
19 import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants;
20 import org.eclipse.jdt.internal.compiler.ASTVisitor;
21 import org.eclipse.jdt.internal.compiler.ast.AND_AND_Expression;
22 import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
23 import org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration;
24 import org.eclipse.jdt.internal.compiler.ast.AllocationExpression;
25 import org.eclipse.jdt.internal.compiler.ast.AnnotationMethodDeclaration;
26 import org.eclipse.jdt.internal.compiler.ast.Argument;
27 import org.eclipse.jdt.internal.compiler.ast.ArrayAllocationExpression;
28 import org.eclipse.jdt.internal.compiler.ast.ArrayInitializer;
29 import org.eclipse.jdt.internal.compiler.ast.ArrayQualifiedTypeReference;
30 import org.eclipse.jdt.internal.compiler.ast.ArrayReference;
31 import org.eclipse.jdt.internal.compiler.ast.ArrayTypeReference;
32 import org.eclipse.jdt.internal.compiler.ast.AssertStatement;
33 import org.eclipse.jdt.internal.compiler.ast.Assignment;
34 import org.eclipse.jdt.internal.compiler.ast.ASTNode;
35 import org.eclipse.jdt.internal.compiler.ast.BinaryExpression;
36 import org.eclipse.jdt.internal.compiler.ast.Block;
37 import org.eclipse.jdt.internal.compiler.ast.BreakStatement;
38 import org.eclipse.jdt.internal.compiler.ast.CaseStatement;
39 import org.eclipse.jdt.internal.compiler.ast.CastExpression;
40 import org.eclipse.jdt.internal.compiler.ast.CharLiteral;
41 import org.eclipse.jdt.internal.compiler.ast.ClassLiteralAccess;
42 import org.eclipse.jdt.internal.compiler.ast.Clinit;
43 import org.eclipse.jdt.internal.compiler.ast.CombinedBinaryExpression;
44 import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
45 import org.eclipse.jdt.internal.compiler.ast.CompoundAssignment;
46 import org.eclipse.jdt.internal.compiler.ast.ConditionalExpression;
47 import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
48 import org.eclipse.jdt.internal.compiler.ast.ContinueStatement;
49 import org.eclipse.jdt.internal.compiler.ast.DoStatement;
50 import org.eclipse.jdt.internal.compiler.ast.DoubleLiteral;
51 import org.eclipse.jdt.internal.compiler.ast.EmptyStatement;
52 import org.eclipse.jdt.internal.compiler.ast.EqualExpression;
53 import org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall;
54 import org.eclipse.jdt.internal.compiler.ast.Expression;
55 import org.eclipse.jdt.internal.compiler.ast.FalseLiteral;
56 import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
57 import org.eclipse.jdt.internal.compiler.ast.FieldReference;
58 import org.eclipse.jdt.internal.compiler.ast.FloatLiteral;
59 import org.eclipse.jdt.internal.compiler.ast.ForStatement;
60 import org.eclipse.jdt.internal.compiler.ast.ForeachStatement;
61 import org.eclipse.jdt.internal.compiler.ast.IfStatement;
62 import org.eclipse.jdt.internal.compiler.ast.ImportReference;
63 import org.eclipse.jdt.internal.compiler.ast.Initializer;
64 import org.eclipse.jdt.internal.compiler.ast.InstanceOfExpression;
65 import org.eclipse.jdt.internal.compiler.ast.IntLiteral;
66 import org.eclipse.jdt.internal.compiler.ast.LabeledStatement;
67 import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
68 import org.eclipse.jdt.internal.compiler.ast.LongLiteral;
69 import org.eclipse.jdt.internal.compiler.ast.MarkerAnnotation;
70 import org.eclipse.jdt.internal.compiler.ast.MemberValuePair;
71 import org.eclipse.jdt.internal.compiler.ast.MessageSend;
72 import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
73 import org.eclipse.jdt.internal.compiler.ast.NormalAnnotation;
74 import org.eclipse.jdt.internal.compiler.ast.ParameterizedQualifiedTypeReference;
75 import org.eclipse.jdt.internal.compiler.ast.ParameterizedSingleTypeReference;
76 import org.eclipse.jdt.internal.compiler.ast.SingleMemberAnnotation;
77 import org.eclipse.jdt.internal.compiler.ast.StringLiteralConcatenation;
78 import org.eclipse.jdt.internal.compiler.ast.NullLiteral;
79 import org.eclipse.jdt.internal.compiler.ast.OR_OR_Expression;
80 import org.eclipse.jdt.internal.compiler.ast.OperatorIds;
81 import org.eclipse.jdt.internal.compiler.ast.PostfixExpression;
82 import org.eclipse.jdt.internal.compiler.ast.PrefixExpression;
83 import org.eclipse.jdt.internal.compiler.ast.QualifiedAllocationExpression;
84 import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference;
85 import org.eclipse.jdt.internal.compiler.ast.QualifiedSuperReference;
86 import org.eclipse.jdt.internal.compiler.ast.QualifiedThisReference;
87 import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference;
88 import org.eclipse.jdt.internal.compiler.ast.ReturnStatement;
89 import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
90 import org.eclipse.jdt.internal.compiler.ast.SingleTypeReference;
91 import org.eclipse.jdt.internal.compiler.ast.Statement;
92 import org.eclipse.jdt.internal.compiler.ast.StringLiteral;
93 import org.eclipse.jdt.internal.compiler.ast.SuperReference;
94 import org.eclipse.jdt.internal.compiler.ast.SwitchStatement;
95 import org.eclipse.jdt.internal.compiler.ast.SynchronizedStatement;
96 import org.eclipse.jdt.internal.compiler.ast.ThisReference;
97 import org.eclipse.jdt.internal.compiler.ast.ThrowStatement;
98 import org.eclipse.jdt.internal.compiler.ast.TrueLiteral;
99 import org.eclipse.jdt.internal.compiler.ast.TryStatement;
100 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
101 import org.eclipse.jdt.internal.compiler.ast.TypeParameter;
102 import org.eclipse.jdt.internal.compiler.ast.TypeReference;
103 import org.eclipse.jdt.internal.compiler.ast.UnaryExpression;
104 import org.eclipse.jdt.internal.compiler.ast.WhileStatement;
105 import org.eclipse.jdt.internal.compiler.ast.Wildcard;
106 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
107 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
108 import org.eclipse.jdt.internal.compiler.impl.Constant;
109 import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
110 import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
111 import org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope;
112 import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
113 import org.eclipse.jdt.internal.compiler.lookup.MethodScope;
114 import org.eclipse.jdt.internal.compiler.parser.Scanner;
115 import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
116 import org.eclipse.jdt.internal.core.util.CodeSnippetParsingUtil;
117 import org.eclipse.jdt.internal.formatter.align.Alignment;
118 import org.eclipse.jdt.internal.formatter.align.AlignmentException;
119 import org.eclipse.jdt.internal.formatter.comment.CommentRegion;
120 import org.eclipse.text.edits.TextEdit;
121
122 /**
123  * This class is responsible for formatting a valid java source code.
124  * @since 2.1
125  */

126 /*
127    <extension
128          id="org.eclipse.jdt.core.newformatter.codeformatter"
129          name="org.eclipse.jdt.core.newformatter.codeformatter"
130          point="org.eclipse.jdt.core.codeFormatter">
131       <codeFormatter
132             class="org.eclipse.jdt.internal.formatter.CodeFormatterVisitor">
133       </codeFormatter>
134    </extension>
135 */

136 public class CodeFormatterVisitor extends ASTVisitor {
137
138     public static class MultiFieldDeclaration extends FieldDeclaration {
139         
140         FieldDeclaration[] declarations;
141         
142         MultiFieldDeclaration(FieldDeclaration[] declarations){
143             this.declarations = declarations;
144             this.modifiers = declarations[0].modifiers;
145         }
146     }
147     
148     public final static boolean DEBUG = false;
149     private static final int NO_MODIFIERS = 0;
150     /*
151      * Set of expected tokens type for a single type reference.
152      * This array needs to be SORTED.
153      */

154     private static final int[] SINGLETYPEREFERENCE_EXPECTEDTOKENS = new int[] {
155         TerminalTokens.TokenNameIdentifier,
156         TerminalTokens.TokenNameboolean,
157         TerminalTokens.TokenNamebyte,
158         TerminalTokens.TokenNamechar,
159         TerminalTokens.TokenNamedouble,
160         TerminalTokens.TokenNamefloat,
161         TerminalTokens.TokenNameint,
162         TerminalTokens.TokenNamelong,
163         TerminalTokens.TokenNameshort,
164         TerminalTokens.TokenNamevoid
165     };
166     private static final int[] CLOSING_GENERICS_EXPECTEDTOKENS = new int[] {
167         TerminalTokens.TokenNameRIGHT_SHIFT,
168         TerminalTokens.TokenNameUNSIGNED_RIGHT_SHIFT,
169         TerminalTokens.TokenNameGREATER
170     };
171     private int chunkKind;
172     public int lastLocalDeclarationSourceStart;
173     private Scanner localScanner;
174     public DefaultCodeFormatterOptions preferences;
175     public Scribe scribe;
176
177     public CodeFormatterVisitor(DefaultCodeFormatterOptions preferences, Map JavaDoc settings, int offset, int length, CodeSnippetParsingUtil codeSnippetParsingUtil) {
178         long sourceLevel = settings == null
179             ? ClassFileConstants.JDK1_3
180             : CompilerOptions.versionToJdkLevel(settings.get(JavaCore.COMPILER_SOURCE));
181         this.localScanner = new Scanner(true, false, false/*nls*/, sourceLevel/*sourceLevel*/, null/*taskTags*/, null/*taskPriorities*/, true/*taskCaseSensitive*/);
182         
183         this.preferences = preferences;
184         this.scribe = new Scribe(this, sourceLevel, offset, length, codeSnippetParsingUtil);
185     }
186     
187     /**
188      * @see org.eclipse.jdt.internal.compiler.ASTVisitor#acceptProblem(org.eclipse.jdt.core.compiler.IProblem)
189      */

190     public void acceptProblem(IProblem problem) {
191         super.acceptProblem(problem);
192     }
193
194     private BinaryExpressionFragmentBuilder buildFragments(BinaryExpression binaryExpression, BlockScope scope) {
195         BinaryExpressionFragmentBuilder builder = new BinaryExpressionFragmentBuilder();
196
197         if (binaryExpression instanceof CombinedBinaryExpression) {
198             binaryExpression.traverse(builder, scope);
199             return builder;
200         }
201         switch((binaryExpression.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT) {
202             case OperatorIds.MULTIPLY :
203                 binaryExpression.left.traverse(builder, scope);
204                 builder.operatorsList.add(new Integer JavaDoc(TerminalTokens.TokenNameMULTIPLY));
205                 binaryExpression.right.traverse(builder, scope);
206                 break;
207             case OperatorIds.PLUS :
208                 binaryExpression.left.traverse(builder, scope);
209                 builder.operatorsList.add(new Integer JavaDoc(TerminalTokens.TokenNamePLUS));
210                 binaryExpression.right.traverse(builder, scope);
211                 break;
212             case OperatorIds.DIVIDE :
213                 binaryExpression.left.traverse(builder, scope);
214                 builder.operatorsList.add(new Integer JavaDoc(TerminalTokens.TokenNameDIVIDE));
215                 binaryExpression.right.traverse(builder, scope);
216                 break;
217             case OperatorIds.REMAINDER :
218                 binaryExpression.left.traverse(builder, scope);
219                 builder.operatorsList.add(new Integer JavaDoc(TerminalTokens.TokenNameREMAINDER));
220                 binaryExpression.right.traverse(builder, scope);
221                 break;
222             case OperatorIds.XOR :
223                 binaryExpression.left.traverse(builder, scope);
224                 builder.operatorsList.add(new Integer JavaDoc(TerminalTokens.TokenNameXOR));
225                 binaryExpression.right.traverse(builder, scope);
226                 break;
227             case OperatorIds.MINUS :
228                 binaryExpression.left.traverse(builder, scope);
229                 builder.operatorsList.add(new Integer JavaDoc(TerminalTokens.TokenNameMINUS));
230                 binaryExpression.right.traverse(builder, scope);
231                 break;
232             case OperatorIds.OR :
233                 binaryExpression.left.traverse(builder, scope);
234                 builder.operatorsList.add(new Integer JavaDoc(TerminalTokens.TokenNameOR));
235                 binaryExpression.right.traverse(builder, scope);
236                 break;
237             case OperatorIds.AND :
238                 binaryExpression.left.traverse(builder, scope);
239                 builder.operatorsList.add(new Integer JavaDoc(TerminalTokens.TokenNameAND));
240                 binaryExpression.right.traverse(builder, scope);
241                 break;
242             case OperatorIds.AND_AND :
243                 binaryExpression.left.traverse(builder, scope);
244                 builder.operatorsList.add(new Integer JavaDoc(TerminalTokens.TokenNameAND_AND));
245                 binaryExpression.right.traverse(builder, scope);
246                 break;
247             case OperatorIds.OR_OR :
248                 binaryExpression.left.traverse(builder, scope);
249                 builder.operatorsList.add(new Integer JavaDoc(TerminalTokens.TokenNameOR_OR));
250                 binaryExpression.right.traverse(builder, scope);
251                 break;
252         }
253
254         return builder;
255     }
256
257     private CascadingMethodInvocationFragmentBuilder buildFragments(MessageSend messageSend, BlockScope scope) {
258         CascadingMethodInvocationFragmentBuilder builder = new CascadingMethodInvocationFragmentBuilder();
259
260         messageSend.traverse(builder, scope);
261         return builder;
262     }
263     public boolean checkChunkStart(int kind) {
264         if (this.chunkKind != kind) {
265             this.chunkKind = kind;
266             return true;
267         }
268         return false;
269     }
270     
271     private boolean commentStartsBlock(int start, int end) {
272         this.localScanner.resetTo(start, end);
273         try {
274             if (this.localScanner.getNextToken() == TerminalTokens.TokenNameLBRACE) {
275                 switch(this.localScanner.getNextToken()) {
276                     case TerminalTokens.TokenNameCOMMENT_BLOCK :
277                     case TerminalTokens.TokenNameCOMMENT_JAVADOC :
278                     case TerminalTokens.TokenNameCOMMENT_LINE :
279                         return true;
280                 }
281             }
282         } catch(InvalidInputException e) {
283             // ignore
284
}
285         return false;
286     }
287
288     private ASTNode[] computeMergedMemberDeclarations(ASTNode[] nodes){
289         ArrayList JavaDoc mergedNodes = new ArrayList JavaDoc();
290         for (int i = 0, max = nodes.length; i < max; i++) {
291             ASTNode currentNode = nodes[i];
292             if (currentNode instanceof FieldDeclaration) {
293                 FieldDeclaration currentField = (FieldDeclaration) currentNode;
294                 if (mergedNodes.size() == 0) {
295                     // first node
296
mergedNodes.add(currentNode);
297                 } else {
298                     // we need to check if the previous merged node is a field declaration
299
ASTNode previousMergedNode = (ASTNode) mergedNodes.get(mergedNodes.size() - 1);
300                     if (previousMergedNode instanceof MultiFieldDeclaration) {
301                         // we merge the current node
302
MultiFieldDeclaration multiFieldDeclaration = (MultiFieldDeclaration) previousMergedNode;
303                         int length = multiFieldDeclaration.declarations.length;
304                         System.arraycopy(multiFieldDeclaration.declarations, 0, multiFieldDeclaration.declarations= new FieldDeclaration[length+1], 0, length);
305                         multiFieldDeclaration.declarations[length] = currentField;
306                     } else if (previousMergedNode instanceof FieldDeclaration) {
307                         // need to check we need to create a multiple field declaration
308
final FieldDeclaration previousFieldDeclaration = (FieldDeclaration)previousMergedNode;
309                         if (currentField.declarationSourceStart == previousFieldDeclaration.declarationSourceStart) {
310                             // we create a multi field declaration
311
final MultiFieldDeclaration multiFieldDeclaration = new MultiFieldDeclaration(new FieldDeclaration[]{ previousFieldDeclaration, currentField});
312                             multiFieldDeclaration.annotations = previousFieldDeclaration.annotations;
313                             mergedNodes.set(mergedNodes.size() - 1, multiFieldDeclaration);
314                         } else {
315                             mergedNodes.add(currentNode);
316                         }
317                     } else {
318                         mergedNodes.add(currentNode);
319                     }
320                 }
321             } else {
322                 mergedNodes.add(currentNode);
323             }
324         }
325         if (mergedNodes.size() != nodes.length) {
326             ASTNode[] result = new ASTNode[mergedNodes.size()];
327             mergedNodes.toArray(result);
328             return result;
329         } else {
330             return nodes;
331         }
332     }
333     
334     private ASTNode[] computeMergedMemberDeclarations(TypeDeclaration typeDeclaration){
335         
336         int fieldIndex = 0, fieldCount = (typeDeclaration.fields == null) ? 0 : typeDeclaration.fields.length;
337         FieldDeclaration field = fieldCount == 0 ? null : typeDeclaration.fields[fieldIndex];
338         int fieldStart = field == null ? Integer.MAX_VALUE : field.declarationSourceStart;
339
340         int methodIndex = 0, methodCount = (typeDeclaration.methods == null) ? 0 : typeDeclaration.methods.length;
341         AbstractMethodDeclaration method = methodCount == 0 ? null : typeDeclaration.methods[methodIndex];
342         int methodStart = method == null ? Integer.MAX_VALUE : method.declarationSourceStart;
343
344         int typeIndex = 0, typeCount = (typeDeclaration.memberTypes == null) ? 0 : typeDeclaration.memberTypes.length;
345         TypeDeclaration type = typeCount == 0 ? null : typeDeclaration.memberTypes[typeIndex];
346         int typeStart = type == null ? Integer.MAX_VALUE : type.declarationSourceStart;
347     
348         final int memberLength = fieldCount+methodCount+typeCount;
349         ASTNode[] members = new ASTNode[memberLength];
350         if (memberLength != 0) {
351             int index = 0;
352             int previousFieldStart = -1;
353             do {
354                 if (fieldStart < methodStart && fieldStart < typeStart) {
355                     if (field.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT) {
356                         // filter out enum constants
357
previousFieldStart = fieldStart;
358                         if (++fieldIndex < fieldCount) { // find next field if any
359
fieldStart = (field = typeDeclaration.fields[fieldIndex]).declarationSourceStart;
360                         } else {
361                             fieldStart = Integer.MAX_VALUE;
362                         }
363                         continue;
364                     }
365                     // next member is a field
366
if (fieldStart == previousFieldStart){
367                         ASTNode previousMember = members[index - 1];
368                         if (previousMember instanceof MultiFieldDeclaration) {
369                             MultiFieldDeclaration multiField = (MultiFieldDeclaration) previousMember;
370                             int length = multiField.declarations.length;
371                             System.arraycopy(multiField.declarations, 0, multiField.declarations=new FieldDeclaration[length+1], 0, length);
372                             multiField.declarations[length] = field;
373                         } else {
374                             FieldDeclaration fieldDeclaration = (FieldDeclaration)previousMember;
375                             final MultiFieldDeclaration multiFieldDeclaration = new MultiFieldDeclaration(new FieldDeclaration[]{ fieldDeclaration, field});
376                             multiFieldDeclaration.annotations = fieldDeclaration.annotations;
377                             members[index - 1] = multiFieldDeclaration;
378                         }
379                     } else {
380                         members[index++] = field;
381                     }
382                     previousFieldStart = fieldStart;
383                     if (++fieldIndex < fieldCount) { // find next field if any
384
fieldStart = (field = typeDeclaration.fields[fieldIndex]).declarationSourceStart;
385                     } else {
386                         fieldStart = Integer.MAX_VALUE;
387                     }
388                 } else if (methodStart < fieldStart && methodStart < typeStart) {
389                     // next member is a method
390
if (!method.isDefaultConstructor() && !method.isClinit()) {
391                         members[index++] = method;
392                     }
393                     if (++methodIndex < methodCount) { // find next method if any
394
methodStart = (method = typeDeclaration.methods[methodIndex]).declarationSourceStart;
395                     } else {
396                         methodStart = Integer.MAX_VALUE;
397                     }
398                 } else {
399                     // next member is a type
400
members[index++] = type;
401                     if (++typeIndex < typeCount) { // find next type if any
402
typeStart = (type = typeDeclaration.memberTypes[typeIndex]).declarationSourceStart;
403                     } else {
404                         typeStart = Integer.MAX_VALUE;
405                     }
406                 }
407             } while ((fieldIndex < fieldCount) || (typeIndex < typeCount) || (methodIndex < methodCount));
408             
409             if (members.length != index) {
410                 System.arraycopy(members, 0, members=new ASTNode[index], 0, index);
411             }
412         }
413         return members;
414     }
415     
416     private boolean dumpBinaryExpression(
417         BinaryExpression binaryExpression,
418         int operator,
419         BlockScope scope) {
420
421         final int numberOfParens = (binaryExpression.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
422
423         if (numberOfParens > 0) {
424             manageOpeningParenthesizedExpression(binaryExpression, numberOfParens);
425         }
426         BinaryExpressionFragmentBuilder builder = buildFragments(binaryExpression, scope);
427         final int fragmentsSize = builder.size();
428         
429         if ((builder.realFragmentsSize() > 1 || builder.size() > 4) && numberOfParens == 0) {
430             this.scribe.printComment();
431             Alignment binaryExpressionAlignment = this.scribe.createAlignment("binaryExpressionAlignment", this.preferences.alignment_for_binary_expression, Alignment.R_OUTERMOST, fragmentsSize, this.scribe.scanner.currentPosition); //$NON-NLS-1$
432
this.scribe.enterAlignment(binaryExpressionAlignment);
433             boolean ok = false;
434             ASTNode[] fragments = builder.fragments();
435             int[] operators = builder.operators();
436             do {
437                 try {
438                     for (int i = 0; i < fragmentsSize - 1; i++) {
439                         ASTNode fragment = fragments[i];
440                         fragment.traverse(this, scope);
441                         this.scribe.printTrailingComment();
442                         if (this.scribe.lastNumberOfNewLines == 1) {
443                             // a new line has been inserted by printTrailingComment()
444
this.scribe.indentationLevel = binaryExpressionAlignment.breakIndentationLevel;
445                         }
446                         if (this.preferences.wrap_before_binary_operator) {
447                             this.scribe.alignFragment(binaryExpressionAlignment, i);
448                             this.scribe.printNextToken(operators[i], this.preferences.insert_space_before_binary_operator);
449                         } else {
450                             this.scribe.printNextToken(operators[i], this.preferences.insert_space_before_binary_operator);
451                             this.scribe.alignFragment(binaryExpressionAlignment, i);
452                         }
453                         if (operators[i] == TerminalTokens.TokenNameMINUS && isNextToken(TerminalTokens.TokenNameMINUS)) {
454                             // the next character is a minus (unary operator)
455
this.scribe.space();
456                         }
457                         if (this.preferences.insert_space_after_binary_operator) {
458                             this.scribe.space();
459                         }
460                     }
461                     fragments[fragmentsSize - 1].traverse(this, scope);
462                     this.scribe.printTrailingComment();
463                     ok = true;
464                 } catch(AlignmentException e){
465                     this.scribe.redoAlignment(e);
466                 }
467             } while (!ok);
468             this.scribe.exitAlignment(binaryExpressionAlignment, true);
469         } else {
470             binaryExpression.left.traverse(this, scope);
471             this.scribe.printNextToken(operator, this.preferences.insert_space_before_binary_operator);
472             if (operator == TerminalTokens.TokenNameMINUS && isNextToken(TerminalTokens.TokenNameMINUS)) {
473                 // the next character is a minus (unary operator)
474
this.scribe.space();
475             }
476             if (this.preferences.insert_space_after_binary_operator) {
477                 this.scribe.space();
478             }
479             binaryExpression.right.traverse(this, scope);
480         }
481         if (numberOfParens > 0) {
482             manageClosingParenthesizedExpression(binaryExpression, numberOfParens);
483         }
484         return false;
485     }
486
487     private boolean dumpEqualityExpression(
488         BinaryExpression binaryExpression,
489         int operator,
490         BlockScope scope) {
491     
492         final int numberOfParens = (binaryExpression.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
493     
494         if (numberOfParens > 0) {
495             manageOpeningParenthesizedExpression(binaryExpression, numberOfParens);
496         }
497         binaryExpression.left.traverse(this, scope);
498         this.scribe.printNextToken(operator, this.preferences.insert_space_before_binary_operator);
499         if (this.preferences.insert_space_after_binary_operator) {
500             this.scribe.space();
501         }
502         binaryExpression.right.traverse(this, scope);
503
504         if (numberOfParens > 0) {
505             manageClosingParenthesizedExpression(binaryExpression, numberOfParens);
506         }
507         return false;
508     }
509
510     private final TextEdit failedToFormat() {
511         if (DEBUG) {
512             System.out.println("COULD NOT FORMAT \n" + this.scribe.scanner); //$NON-NLS-1$
513
System.out.println(this.scribe);
514         }
515         return null;
516     }
517
518     private void format(
519         AbstractMethodDeclaration methodDeclaration,
520         ClassScope scope,
521         boolean isChunkStart,
522         boolean isFirstClassBodyDeclaration) {
523
524         if (isFirstClassBodyDeclaration) {
525             int newLinesBeforeFirstClassBodyDeclaration = this.preferences.blank_lines_before_first_class_body_declaration;
526             if (newLinesBeforeFirstClassBodyDeclaration > 0) {
527                 this.scribe.printEmptyLines(newLinesBeforeFirstClassBodyDeclaration);
528             }
529         } else {
530             final int newLineBeforeChunk = isChunkStart ? this.preferences.blank_lines_before_new_chunk : 0;
531             if (newLineBeforeChunk > 0) {
532                 this.scribe.printEmptyLines(newLineBeforeChunk);
533             }
534         }
535         final int newLinesBeforeMethod = this.preferences.blank_lines_before_method;
536         if (newLinesBeforeMethod > 0 && !isFirstClassBodyDeclaration) {
537             this.scribe.printEmptyLines(newLinesBeforeMethod);
538         } else if (this.scribe.line != 0 || this.scribe.column != 1) {
539             this.scribe.printNewLine();
540         }
541         methodDeclaration.traverse(this, scope);
542     }
543
544     private void format(FieldDeclaration fieldDeclaration, ASTVisitor visitor, MethodScope scope, boolean isChunkStart, boolean isFirstClassBodyDeclaration) {
545         
546         if (isFirstClassBodyDeclaration) {
547             int newLinesBeforeFirstClassBodyDeclaration = this.preferences.blank_lines_before_first_class_body_declaration;
548             if (newLinesBeforeFirstClassBodyDeclaration > 0) {
549                 this.scribe.printEmptyLines(newLinesBeforeFirstClassBodyDeclaration);
550             }
551         } else {
552             int newLineBeforeChunk = isChunkStart ? this.preferences.blank_lines_before_new_chunk : 0;
553             if (newLineBeforeChunk > 0) {
554                 this.scribe.printEmptyLines(newLineBeforeChunk);
555             }
556             final int newLinesBeforeField = this.preferences.blank_lines_before_field;
557             if (newLinesBeforeField > 0) {
558                 this.scribe.printEmptyLines(newLinesBeforeField);
559             }
560         }
561         Alignment memberAlignment = this.scribe.getMemberAlignment();
562     
563         this.scribe.printComment();
564         this.scribe.printModifiers(fieldDeclaration.annotations, this);
565         this.scribe.space();
566         /*
567          * Field type
568          */

569         fieldDeclaration.type.traverse(this, scope);
570         
571         /*
572          * Field name
573          */

574         this.scribe.alignFragment(memberAlignment, 0);
575     
576         this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, true);
577     
578         /*
579          * Check for extra dimensions
580          */

581         int extraDimensions = getDimensions();
582         if (extraDimensions != 0) {
583              for (int i = 0; i < extraDimensions; i++) {
584                 this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET);
585                 this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET);
586              }
587         }
588     
589         /*
590          * Field initialization
591          */

592         final Expression initialization = fieldDeclaration.initialization;
593         if (initialization != null) {
594             this.scribe.alignFragment(memberAlignment, 1);
595             this.scribe.printNextToken(TerminalTokens.TokenNameEQUAL, this.preferences.insert_space_before_assignment_operator);
596             if (this.preferences.insert_space_after_assignment_operator) {
597                 this.scribe.space();
598             }
599             Alignment assignmentAlignment = this.scribe.createAlignment("fieldDeclarationAssignmentAlignment", this.preferences.alignment_for_assignment, Alignment.R_OUTERMOST, 1, this.scribe.scanner.currentPosition); //$NON-NLS-1$
600
this.scribe.enterAlignment(assignmentAlignment);
601             boolean ok = false;
602             do {
603                 try {
604                     this.scribe.alignFragment(assignmentAlignment, 0);
605                     initialization.traverse(this, scope);
606                     ok = true;
607                 } catch(AlignmentException e){
608                     this.scribe.redoAlignment(e);
609                 }
610             } while (!ok);
611             this.scribe.exitAlignment(assignmentAlignment, true);
612         }
613         
614         this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
615
616         if (memberAlignment != null) {
617             this.scribe.alignFragment(memberAlignment, 2);
618             this.scribe.printTrailingComment();
619         } else {
620             this.scribe.space();
621             this.scribe.printTrailingComment();
622         }
623     }
624     
625     private void format(ImportReference importRef, boolean isLast) {
626         this.scribe.printNextToken(TerminalTokens.TokenNameimport);
627         this.preferences.number_of_empty_lines_to_preserve = this.preferences.blank_lines_between_import_groups;
628         this.scribe.space();
629         if (importRef.isStatic()) {
630             this.scribe.printNextToken(TerminalTokens.TokenNamestatic);
631             this.scribe.space();
632         }
633         if ((importRef.bits & ASTNode.OnDemand) != 0) {
634             this.scribe.printQualifiedReference(importRef.sourceEnd);
635             this.scribe.printNextToken(TerminalTokens.TokenNameDOT);
636             this.scribe.printNextToken(TerminalTokens.TokenNameMULTIPLY);
637             this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
638         } else {
639             this.scribe.printQualifiedReference(importRef.sourceEnd);
640             this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
641         }
642         if (isLast) {
643             this.scribe.printTrailingComment();
644         } else {
645             this.scribe.printTrailingComment(this.preferences.blank_lines_between_import_groups);
646         }
647         this.scribe.printNewLine();
648     }
649
650
651     private void format(MultiFieldDeclaration multiFieldDeclaration, ASTVisitor visitor, MethodScope scope, boolean isChunkStart, boolean isFirstClassBodyDeclaration) {
652     
653         if (isFirstClassBodyDeclaration) {
654             int newLinesBeforeFirstClassBodyDeclaration = this.preferences.blank_lines_before_first_class_body_declaration;
655             if (newLinesBeforeFirstClassBodyDeclaration > 0) {
656                 this.scribe.printEmptyLines(newLinesBeforeFirstClassBodyDeclaration);
657             }
658         } else {
659             int newLineBeforeChunk = isChunkStart ? this.preferences.blank_lines_before_new_chunk : 0;
660             if (newLineBeforeChunk > 0) {
661                 this.scribe.printEmptyLines(newLineBeforeChunk);
662             }
663             final int newLinesBeforeField = this.preferences.blank_lines_before_field;
664             if (newLinesBeforeField > 0) {
665                 this.scribe.printEmptyLines(newLinesBeforeField);
666             }
667         }
668         Alignment fieldAlignment = this.scribe.getMemberAlignment();
669     
670         this.scribe.printComment();
671         this.scribe.printModifiers(multiFieldDeclaration.annotations, this);
672         this.scribe.space();
673     
674         multiFieldDeclaration.declarations[0].type.traverse(this, scope);
675     
676         final int multipleFieldDeclarationsLength = multiFieldDeclaration.declarations.length;
677
678         Alignment multiFieldDeclarationsAlignment =this.scribe.createAlignment(
679                 "multiple_field",//$NON-NLS-1$
680
this.preferences.alignment_for_multiple_fields,
681                 multipleFieldDeclarationsLength - 1,
682                 this.scribe.scanner.currentPosition);
683         this.scribe.enterAlignment(multiFieldDeclarationsAlignment);
684     
685         boolean ok = false;
686         do {
687             try {
688                 for (int i = 0, length = multipleFieldDeclarationsLength; i < length; i++) {
689                     FieldDeclaration fieldDeclaration = multiFieldDeclaration.declarations[i];
690                     /*
691                      * Field name
692                      */

693                     if (i == 0) {
694                         this.scribe.alignFragment(fieldAlignment, 0);
695                         this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, true);
696                     } else {
697                         this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, false);
698                     }
699             
700                     /*
701                      * Check for extra dimensions
702                      */

703                     int extraDimensions = getDimensions();
704                     if (extraDimensions != 0) {
705                          for (int index = 0; index < extraDimensions; index++) {
706                             this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET);
707                             this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET);
708                          }
709                     }
710                 
711                     /*
712                      * Field initialization
713                      */

714                     final Expression initialization = fieldDeclaration.initialization;
715                     if (initialization != null) {
716                         if (i == 0) {
717                             this.scribe.alignFragment(fieldAlignment, 1);
718                         }
719                         this.scribe.printNextToken(TerminalTokens.TokenNameEQUAL, this.preferences.insert_space_before_assignment_operator);
720                         if (this.preferences.insert_space_after_assignment_operator) {
721                             this.scribe.space();
722                         }
723                         initialization.traverse(this, scope);
724                     }
725                     
726                     if (i != length - 1) {
727                         this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_multiple_field_declarations);
728                         this.scribe.printTrailingComment();
729                         this.scribe.alignFragment(multiFieldDeclarationsAlignment, i);
730
731                         if (this.preferences.insert_space_after_comma_in_multiple_field_declarations) {
732                             this.scribe.space();
733                         }
734                     } else {
735                         this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
736                         this.scribe.alignFragment(fieldAlignment, 2);
737                         this.scribe.printTrailingComment();
738                     }
739                 }
740                 ok = true;
741             } catch (AlignmentException e) {
742                 this.scribe.redoAlignment(e);
743             }
744         } while (!ok);
745         this.scribe.exitAlignment(multiFieldDeclarationsAlignment, true);
746     }
747     
748     /**
749      * @see org.eclipse.jdt.core.formatter.CodeFormatter#format(int, String, int, int, int, String)
750      */

751     public TextEdit format(String JavaDoc string, ASTNode[] nodes) {
752         // reset the scribe
753
this.scribe.reset();
754         
755         long startTime = System.currentTimeMillis();
756
757         final char[] compilationUnitSource = string.toCharArray();
758         
759         this.localScanner.setSource(compilationUnitSource);
760         this.scribe.initializeScanner(compilationUnitSource);
761
762         if (nodes == null) {
763             return null;
764         }
765
766         this.lastLocalDeclarationSourceStart = -1;
767         try {
768             formatClassBodyDeclarations(nodes);
769         } catch(AbortFormatting e){
770             return failedToFormat();
771         }
772         if (DEBUG){
773             System.out.println("Formatting time: " + (System.currentTimeMillis() - startTime)); //$NON-NLS-1$
774
}
775         return this.scribe.getRootEdit();
776     }
777
778     /**
779      * @see org.eclipse.jdt.core.formatter.CodeFormatter#format(int, String, int, int, int, String)
780      */

781     public TextEdit format(String JavaDoc string, CompilationUnitDeclaration compilationUnitDeclaration) {
782         // reset the scribe
783
this.scribe.reset();
784         
785         if (compilationUnitDeclaration == null || compilationUnitDeclaration.ignoreFurtherInvestigation) {
786             return failedToFormat();
787         }
788
789         long startTime = System.currentTimeMillis();
790
791         final char[] compilationUnitSource = string.toCharArray();
792         
793         this.localScanner.setSource(compilationUnitSource);
794         this.scribe.initializeScanner(compilationUnitSource);
795
796         this.lastLocalDeclarationSourceStart = -1;
797         try {
798             compilationUnitDeclaration.traverse(this, compilationUnitDeclaration.scope);
799         } catch(AbortFormatting e){
800             return failedToFormat();
801         }
802         if (DEBUG){
803             System.out.println("Formatting time: " + (System.currentTimeMillis() - startTime)); //$NON-NLS-1$
804
}
805         return this.scribe.getRootEdit();
806     }
807
808     /**
809      * @see org.eclipse.jdt.core.formatter.CodeFormatter#format(int, String, int, int, int, String)
810      */

811     public TextEdit format(String JavaDoc string, ConstructorDeclaration constructorDeclaration) {
812         // reset the scribe
813
this.scribe.reset();
814         
815         long startTime = System.currentTimeMillis();
816
817         final char[] compilationUnitSource = string.toCharArray();
818         
819         this.localScanner.setSource(compilationUnitSource);
820         this.scribe.initializeScanner(compilationUnitSource);
821
822         if (constructorDeclaration == null) {
823             return null;
824         }
825
826         this.lastLocalDeclarationSourceStart = -1;
827         try {
828             ExplicitConstructorCall explicitConstructorCall = constructorDeclaration.constructorCall;
829             if (explicitConstructorCall != null && !explicitConstructorCall.isImplicitSuper()) {
830                 explicitConstructorCall.traverse(this, null);
831             }
832             Statement[] statements = constructorDeclaration.statements;
833             if (statements != null) {
834                 formatStatements(null, statements, false);
835             }
836             if (hasComments()) {
837                 this.scribe.printNewLine();
838             }
839             this.scribe.printComment();
840         } catch(AbortFormatting e){
841             return failedToFormat();
842         }
843         if (DEBUG){
844             System.out.println("Formatting time: " + (System.currentTimeMillis() - startTime)); //$NON-NLS-1$
845
}
846         return this.scribe.getRootEdit();
847     }
848
849     /**
850      * @see org.eclipse.jdt.core.formatter.CodeFormatter#format(int, String, int, int, int, String)
851      */

852     public TextEdit format(String JavaDoc string, Expression expression) {
853         // reset the scribe
854
this.scribe.reset();
855         
856         long startTime = System.currentTimeMillis();
857
858         final char[] compilationUnitSource = string.toCharArray();
859         
860         this.localScanner.setSource(compilationUnitSource);
861         this.scribe.initializeScanner(compilationUnitSource);
862
863         if (expression == null) {
864             return null;
865         }
866
867         this.lastLocalDeclarationSourceStart = -1;
868         try {
869             expression.traverse(this, (BlockScope) null);
870             this.scribe.printComment();
871         } catch(AbortFormatting e){
872             return failedToFormat();
873         }
874         if (DEBUG){
875             System.out.println("Formatting time: " + (System.currentTimeMillis() - startTime)); //$NON-NLS-1$
876
}
877         return this.scribe.getRootEdit();
878     }
879     
880     /**
881      * @see org.eclipse.jdt.core.formatter.CodeFormatter#format(int, String, int, int, int, String)
882      */

883     public TextEdit format(String JavaDoc string, CommentRegion region) {
884         // reset the scribe
885
this.scribe.reset();
886         
887         if (region == null) {
888             return failedToFormat();
889         }
890
891         long startTime = 0;
892         if (DEBUG){
893             startTime = System.currentTimeMillis();
894         }
895
896         final char[] compilationUnitSource = string.toCharArray();
897         
898         this.scribe.initializeScanner(compilationUnitSource);
899
900         TextEdit result = null;
901         try {
902             result = region.format(this.preferences.initial_indentation_level, true);
903         } catch(AbortFormatting e){
904             return failedToFormat();
905         }
906         if (DEBUG){
907             System.out.println("Formatting time: " + (System.currentTimeMillis() - startTime)); //$NON-NLS-1$
908
}
909         return result;
910     }
911
912     private void format(TypeDeclaration typeDeclaration){
913         /*
914          * Print comments to get proper line number
915          */

916         this.scribe.printComment();
917         int line = this.scribe.line;
918
919         this.scribe.printModifiers(typeDeclaration.annotations, this);
920
921         if (this.scribe.line > line) {
922             // annotations introduced new line, but this is not a line wrapping
923
// see 158267
924
line = this.scribe.line;
925         }
926
927         /*
928          * Type name
929          */

930         switch(TypeDeclaration.kind(typeDeclaration.modifiers)) {
931             case TypeDeclaration.CLASS_DECL :
932                 this.scribe.printNextToken(TerminalTokens.TokenNameclass, true);
933                 break;
934             case TypeDeclaration.INTERFACE_DECL :
935                 this.scribe.printNextToken(TerminalTokens.TokenNameinterface, true);
936                 break;
937             case TypeDeclaration.ENUM_DECL :
938                 this.scribe.printNextToken(TerminalTokens.TokenNameenum, true);
939                 break;
940             case TypeDeclaration.ANNOTATION_TYPE_DECL :
941                 this.scribe.printNextToken(TerminalTokens.TokenNameAT, this.preferences.insert_space_before_at_in_annotation_type_declaration);
942                 this.scribe.printNextToken(TerminalTokens.TokenNameinterface, this.preferences.insert_space_after_at_in_annotation_type_declaration);
943                 break;
944         }
945         this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, true);
946
947         TypeParameter[] typeParameters = typeDeclaration.typeParameters;
948         if (typeParameters != null) {
949             this.scribe.printNextToken(TerminalTokens.TokenNameLESS, this.preferences.insert_space_before_opening_angle_bracket_in_type_parameters);
950             if (this.preferences.insert_space_after_opening_angle_bracket_in_type_parameters) {
951                 this.scribe.space();
952             }
953             int length = typeParameters.length;
954             for (int i = 0; i < length - 1; i++) {
955                 typeParameters[i].traverse(this, typeDeclaration.scope);
956                 this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_type_parameters);
957                 if (this.preferences.insert_space_after_comma_in_type_parameters) {
958                     this.scribe.space();
959                 }
960             }
961             typeParameters[length - 1].traverse(this, typeDeclaration.scope);
962             if (isClosingGenericToken()) {
963                 this.scribe.printNextToken(CLOSING_GENERICS_EXPECTEDTOKENS, this.preferences.insert_space_before_closing_angle_bracket_in_type_parameters);
964             }
965             if (this.preferences.insert_space_after_closing_angle_bracket_in_type_parameters) {
966                 this.scribe.space();
967             }
968         }
969         /*
970          * Superclass
971          */

972         final TypeReference superclass = typeDeclaration.superclass;
973         if (superclass != null) {
974             Alignment superclassAlignment =this.scribe.createAlignment(
975                     "superclass", //$NON-NLS-1$
976
this.preferences.alignment_for_superclass_in_type_declaration,
977                     2,
978                     this.scribe.scanner.currentPosition);
979             this.scribe.enterAlignment(superclassAlignment);
980             boolean ok = false;
981             do {
982                 try {
983                     this.scribe.alignFragment(superclassAlignment, 0);
984                     this.scribe.printNextToken(TerminalTokens.TokenNameextends, true);
985                     this.scribe.alignFragment(superclassAlignment, 1);
986                     this.scribe.space();
987                     superclass.traverse(this, typeDeclaration.scope);
988                     ok = true;
989                 } catch (AlignmentException e) {
990                     this.scribe.redoAlignment(e);
991                 }
992             } while (!ok);
993             this.scribe.exitAlignment(superclassAlignment, true);
994         }
995
996         /*
997          * Super Interfaces
998          */

999         final TypeReference[] superInterfaces = typeDeclaration.superInterfaces;
1000        if (superInterfaces != null) {
1001            int alignment_for_superinterfaces;
1002            int kind = TypeDeclaration.kind(typeDeclaration.modifiers);
1003            switch(kind) {
1004                case TypeDeclaration.ENUM_DECL :
1005                    alignment_for_superinterfaces = this.preferences.alignment_for_superinterfaces_in_enum_declaration;
1006                    break;
1007                default:
1008                    alignment_for_superinterfaces = this.preferences.alignment_for_superinterfaces_in_type_declaration;
1009                    break;
1010            }
1011            int superInterfaceLength = superInterfaces.length;
1012            Alignment interfaceAlignment =this.scribe.createAlignment(
1013                    "superInterfaces",//$NON-NLS-1$
1014
alignment_for_superinterfaces,
1015                    superInterfaceLength+1, // implements token is first fragment
1016
this.scribe.scanner.currentPosition);
1017            this.scribe.enterAlignment(interfaceAlignment);
1018            boolean ok = false;
1019            do {
1020                try {
1021                    this.scribe.alignFragment(interfaceAlignment, 0);
1022                    if (kind == TypeDeclaration.INTERFACE_DECL) {
1023                        this.scribe.printNextToken(TerminalTokens.TokenNameextends, true);
1024                    } else {
1025                        this.scribe.printNextToken(TerminalTokens.TokenNameimplements, true);
1026                    }
1027                    for (int i = 0; i < superInterfaceLength; i++) {
1028                        if (i > 0) {
1029                            this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_superinterfaces);
1030                            this.scribe.printTrailingComment();
1031                            this.scribe.alignFragment(interfaceAlignment, i+1);
1032                            if (this.preferences.insert_space_after_comma_in_superinterfaces) {
1033                                this.scribe.space();
1034                            }
1035                            superInterfaces[i].traverse(this, typeDeclaration.scope);
1036                        } else {
1037                            this.scribe.alignFragment(interfaceAlignment, i+1);
1038                            this.scribe.space();
1039                            superInterfaces[i].traverse(this, typeDeclaration.scope);
1040                        }
1041                    }
1042                    ok = true;
1043                } catch (AlignmentException e) {
1044                    this.scribe.redoAlignment(e);
1045                }
1046            } while (!ok);
1047            this.scribe.exitAlignment(interfaceAlignment, true);
1048        }
1049
1050        /*
1051         * Type body
1052         */

1053        String JavaDoc class_declaration_brace;
1054        boolean space_before_opening_brace;
1055        int kind = TypeDeclaration.kind(typeDeclaration.modifiers);
1056        switch(kind) {
1057            case TypeDeclaration.ENUM_DECL :
1058                class_declaration_brace = this.preferences.brace_position_for_enum_declaration;
1059                space_before_opening_brace = this.preferences.insert_space_before_opening_brace_in_enum_declaration;
1060                break;
1061            case TypeDeclaration.ANNOTATION_TYPE_DECL :
1062                class_declaration_brace = this.preferences.brace_position_for_annotation_type_declaration;
1063                space_before_opening_brace = this.preferences.insert_space_before_opening_brace_in_annotation_type_declaration;
1064                break;
1065            default:
1066                class_declaration_brace = this.preferences.brace_position_for_type_declaration;
1067                space_before_opening_brace = this.preferences.insert_space_before_opening_brace_in_type_declaration;
1068                break;
1069        }
1070        formatLeftCurlyBrace(line, class_declaration_brace);
1071        formatTypeOpeningBrace(class_declaration_brace, space_before_opening_brace, typeDeclaration);
1072        
1073        boolean indent_body_declarations_compare_to_header;
1074        switch(kind) {
1075            case TypeDeclaration.ENUM_DECL :
1076                indent_body_declarations_compare_to_header = this.preferences.indent_body_declarations_compare_to_enum_declaration_header;
1077                break;
1078            case TypeDeclaration.ANNOTATION_TYPE_DECL :
1079                indent_body_declarations_compare_to_header = this.preferences.indent_body_declarations_compare_to_annotation_declaration_header;
1080                break;
1081            default:
1082                indent_body_declarations_compare_to_header = this.preferences.indent_body_declarations_compare_to_type_header;
1083                break;
1084        }
1085        if (indent_body_declarations_compare_to_header) {
1086            this.scribe.indent();
1087        }
1088        
1089        if (kind == TypeDeclaration.ENUM_DECL) {
1090            FieldDeclaration[] fieldDeclarations = typeDeclaration.fields;
1091            boolean hasConstants = false;
1092            if (fieldDeclarations != null) {
1093                int length = fieldDeclarations.length;
1094                int enumConstantsLength = 0;
1095                for (int i = 0; i < length; i++) {
1096                    FieldDeclaration fieldDeclaration = fieldDeclarations[i];
1097                    if (fieldDeclaration.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT) {
1098                        enumConstantsLength++;
1099                    } else {
1100                        break;
1101                    }
1102                }
1103                hasConstants = enumConstantsLength != 0;
1104                if (enumConstantsLength > 1) {
1105                    Alignment enumConstantsAlignment = this.scribe.createAlignment(
1106                            "enumConstants",//$NON-NLS-1$
1107
this.preferences.alignment_for_enum_constants,
1108                            enumConstantsLength,
1109                            this.scribe.scanner.currentPosition,
1110                            0, // we don't want to indent enum constants when splitting to a new line
1111
false);
1112                    this.scribe.enterAlignment(enumConstantsAlignment);
1113                    boolean ok = false;
1114                    do {
1115                        try {
1116                            for (int i = 0; i < enumConstantsLength; i++) {
1117                                this.scribe.alignFragment(enumConstantsAlignment, i);
1118                                FieldDeclaration fieldDeclaration = fieldDeclarations[i];
1119                                fieldDeclaration.traverse(this, typeDeclaration.initializerScope);
1120                                if (isNextToken(TerminalTokens.TokenNameCOMMA)) {
1121                                    this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_enum_declarations);
1122                                    if (this.preferences.insert_space_after_comma_in_enum_declarations) {
1123                                        this.scribe.space();
1124                                    }
1125                                    this.scribe.printTrailingComment();
1126                                    if (fieldDeclaration.initialization instanceof QualifiedAllocationExpression) {
1127                                        this.scribe.printNewLine();
1128                                    }
1129                                }
1130                            }
1131                            ok = true;
1132                        } catch (AlignmentException e) {
1133                            this.scribe.redoAlignment(e);
1134                        }
1135                    } while (!ok);
1136                    this.scribe.exitAlignment(enumConstantsAlignment, true);
1137                } else {
1138                    FieldDeclaration fieldDeclaration = fieldDeclarations[0];
1139                    fieldDeclaration.traverse(this, typeDeclaration.initializerScope);
1140                    if (isNextToken(TerminalTokens.TokenNameCOMMA)) {
1141                        this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_enum_declarations);
1142                        if (this.preferences.insert_space_after_comma_in_enum_declarations) {
1143                            this.scribe.space();
1144                        }
1145                        this.scribe.printTrailingComment();
1146                        if (fieldDeclaration.initialization instanceof QualifiedAllocationExpression) {
1147                            this.scribe.printNewLine();
1148                        }
1149                    }
1150                }
1151            }
1152            if (isNextToken(TerminalTokens.TokenNameSEMICOLON)) {
1153                this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
1154                this.scribe.printTrailingComment();
1155            }
1156            if (hasConstants) {
1157                this.scribe.printNewLine();
1158            }
1159        }
1160
1161        formatTypeMembers(typeDeclaration);
1162        
1163        if (indent_body_declarations_compare_to_header) {
1164            this.scribe.unIndent();
1165        }
1166        
1167        switch(kind) {
1168            case TypeDeclaration.ENUM_DECL :
1169                if (this.preferences.insert_new_line_in_empty_enum_declaration) {
1170                    this.scribe.printNewLine();
1171                }
1172                break;
1173            case TypeDeclaration.ANNOTATION_TYPE_DECL :
1174                if (this.preferences.insert_new_line_in_empty_annotation_declaration) {
1175                    this.scribe.printNewLine();
1176                }
1177                break;
1178            default :
1179                if (this.preferences.insert_new_line_in_empty_type_declaration) {
1180                    this.scribe.printNewLine();
1181                }
1182        }
1183        this.scribe.printNextToken(TerminalTokens.TokenNameRBRACE);
1184        this.scribe.printTrailingComment();
1185        if (class_declaration_brace.equals(DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED)) {
1186            this.scribe.unIndent();
1187        }
1188        if (hasComments()) {
1189            this.scribe.printNewLine();
1190        }
1191    }
1192
1193    private void format(
1194        TypeDeclaration memberTypeDeclaration,
1195        ClassScope scope,
1196        boolean isChunkStart,
1197        boolean isFirstClassBodyDeclaration) {
1198
1199        if (isFirstClassBodyDeclaration) {
1200            int newLinesBeforeFirstClassBodyDeclaration = this.preferences.blank_lines_before_first_class_body_declaration;
1201            if (newLinesBeforeFirstClassBodyDeclaration > 0) {
1202                this.scribe.printEmptyLines(newLinesBeforeFirstClassBodyDeclaration);
1203            }
1204        } else {
1205            int newLineBeforeChunk = isChunkStart ? this.preferences.blank_lines_before_new_chunk : 0;
1206            if (newLineBeforeChunk > 0) {
1207                this.scribe.printEmptyLines(newLineBeforeChunk);
1208            }
1209            final int newLinesBeforeMember = this.preferences.blank_lines_before_member_type;
1210            if (newLinesBeforeMember > 0) {
1211                this.scribe.printEmptyLines(newLinesBeforeMember);
1212            }
1213        }
1214        memberTypeDeclaration.traverse(this, scope);
1215    }
1216    
1217    private void formatAnonymousTypeDeclaration(TypeDeclaration typeDeclaration) {
1218        /*
1219         * Type body
1220         */

1221        String JavaDoc anonymous_type_declaration_brace_position = this.preferences.brace_position_for_anonymous_type_declaration;
1222        
1223        formatTypeOpeningBrace(anonymous_type_declaration_brace_position, this.preferences.insert_space_before_opening_brace_in_anonymous_type_declaration, typeDeclaration);
1224        
1225        this.scribe.indent();
1226
1227        formatTypeMembers(typeDeclaration);
1228
1229        this.scribe.unIndent();
1230        if (this.preferences.insert_new_line_in_empty_anonymous_type_declaration) {
1231            this.scribe.printNewLine();
1232        }
1233        this.scribe.printNextToken(TerminalTokens.TokenNameRBRACE);
1234        if (anonymous_type_declaration_brace_position.equals(DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED)) {
1235            this.scribe.unIndent();
1236        }
1237    }
1238    
1239    /**
1240     * @param block
1241     * @param scope
1242     * @param block_brace_position
1243     */

1244    private void formatBlock(Block block, BlockScope scope, String JavaDoc block_brace_position, boolean insertSpaceBeforeOpeningBrace) {
1245        formatOpeningBrace(block_brace_position, insertSpaceBeforeOpeningBrace);
1246        final Statement[] statements = block.statements;
1247        if (statements != null) {
1248            this.scribe.printNewLine();
1249            if (this.preferences.indent_statements_compare_to_block) {
1250                this.scribe.indent();
1251            }
1252            formatStatements(scope, statements, true);
1253            this.scribe.printComment();
1254    
1255            if (this.preferences.indent_statements_compare_to_block) {
1256                this.scribe.unIndent();
1257            }
1258        } else if (this.preferences.insert_new_line_in_empty_block) {
1259            this.scribe.printNewLine();
1260            if (this.preferences.indent_statements_compare_to_block) {
1261                this.scribe.indent();
1262            }
1263            this.scribe.printComment();
1264    
1265            if (this.preferences.indent_statements_compare_to_block) {
1266                this.scribe.unIndent();
1267            }
1268        } else {
1269            if (this.preferences.indent_statements_compare_to_block) {
1270                this.scribe.indent();
1271            }
1272            this.scribe.printComment();
1273    
1274            if (this.preferences.indent_statements_compare_to_block) {
1275                this.scribe.unIndent();
1276            }
1277        }
1278        this.scribe.printNextToken(TerminalTokens.TokenNameRBRACE);
1279        this.scribe.printTrailingComment();
1280        if (DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED.equals(block_brace_position)) {
1281            this.scribe.unIndent();
1282        }
1283    }
1284
1285    private void formatCascadingMessageSends(CascadingMethodInvocationFragmentBuilder builder, BlockScope scope) {
1286        int size = builder.size();
1287        MessageSend[] fragments = builder.fragments();
1288        Expression fragment = fragments[0].receiver;
1289        int startingPositionInCascade = 1;
1290        if (!fragment.isImplicitThis()) {
1291            fragment.traverse(this, scope);
1292        } else {
1293            MessageSend currentMessageSend = fragments[1];
1294            final int numberOfParens = (currentMessageSend.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
1295            if (numberOfParens > 0) {
1296                manageOpeningParenthesizedExpression(currentMessageSend, numberOfParens);
1297            }
1298            ASTNode[] arguments = currentMessageSend.arguments;
1299            TypeReference[] typeArguments = currentMessageSend.typeArguments;
1300            if (typeArguments != null) {
1301                    this.scribe.printNextToken(TerminalTokens.TokenNameLESS, this.preferences.insert_space_before_opening_angle_bracket_in_type_arguments);
1302                    if (this.preferences.insert_space_after_opening_angle_bracket_in_type_arguments) {
1303                        this.scribe.space();
1304                    }
1305                    int length = typeArguments.length;
1306                    for (int i = 0; i < length - 1; i++) {
1307                        typeArguments[i].traverse(this, scope);
1308                        this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_type_arguments);
1309                        if (this.preferences.insert_space_after_comma_in_type_arguments) {
1310                            this.scribe.space();
1311                        }
1312                    }
1313                    typeArguments[length - 1].traverse(this, scope);
1314                    if (isClosingGenericToken()) {
1315                        this.scribe.printNextToken(CLOSING_GENERICS_EXPECTEDTOKENS, this.preferences.insert_space_before_closing_angle_bracket_in_type_arguments);
1316                    }
1317                    if (this.preferences.insert_space_after_closing_angle_bracket_in_type_arguments) {
1318                        this.scribe.space();
1319                    }
1320            }
1321            this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier); // selector
1322
this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_method_invocation);
1323            if (arguments != null) {
1324                if (this.preferences.insert_space_after_opening_paren_in_method_invocation) {
1325                    this.scribe.space();
1326                }
1327                int argumentLength = arguments.length;
1328                Alignment argumentsAlignment = this.scribe.createAlignment(
1329                        "messageArguments", //$NON-NLS-1$
1330
this.preferences.alignment_for_arguments_in_method_invocation,
1331                        Alignment.R_OUTERMOST,
1332                        argumentLength,
1333                        this.scribe.scanner.currentPosition);
1334                this.scribe.enterAlignment(argumentsAlignment);
1335                boolean okForArguments = false;
1336                do {
1337                    try {
1338                        for (int j = 0; j < argumentLength; j++) {
1339                            if (j > 0) {
1340                                this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_method_invocation_arguments);
1341                                this.scribe.printTrailingComment();
1342                            }
1343                            this.scribe.alignFragment(argumentsAlignment, j);
1344                            if (j > 0 && this.preferences.insert_space_after_comma_in_method_invocation_arguments) {
1345                                this.scribe.space();
1346                            }
1347                            arguments[j].traverse(this, scope);
1348                        }
1349                        okForArguments = true;
1350                    } catch (AlignmentException e) {
1351                        this.scribe.redoAlignment(e);
1352                    }
1353                } while (!okForArguments);
1354                this.scribe.exitAlignment(argumentsAlignment, true);
1355                this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_method_invocation);
1356            } else {
1357                this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_between_empty_parens_in_method_invocation);
1358            }
1359            if (numberOfParens > 0) {
1360                manageClosingParenthesizedExpression(currentMessageSend, numberOfParens);
1361            }
1362            startingPositionInCascade = 2;
1363        }
1364        Alignment cascadingMessageSendAlignment =
1365            this.scribe.createAlignment(
1366                "cascadingMessageSendAlignment", //$NON-NLS-1$
1367
this.preferences.alignment_for_selector_in_method_invocation,
1368                Alignment.R_INNERMOST,
1369                size,
1370                this.scribe.scanner.currentPosition);
1371        this.scribe.enterAlignment(cascadingMessageSendAlignment);
1372        boolean ok = false;
1373        do {
1374            try {
1375                this.scribe.alignFragment(cascadingMessageSendAlignment, 0);
1376                this.scribe.printNextToken(TerminalTokens.TokenNameDOT);
1377                for (int i = startingPositionInCascade; i < size; i++) {
1378                    MessageSend currentMessageSend = fragments[i];
1379                    final int numberOfParens = (currentMessageSend.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
1380                    if (numberOfParens > 0) {
1381                        manageOpeningParenthesizedExpression(currentMessageSend, numberOfParens);
1382                    }
1383                    TypeReference[] typeArguments = currentMessageSend.typeArguments;
1384                    if (typeArguments != null) {
1385                            this.scribe.printNextToken(TerminalTokens.TokenNameLESS, this.preferences.insert_space_before_opening_angle_bracket_in_type_arguments);
1386                            if (this.preferences.insert_space_after_opening_angle_bracket_in_type_arguments) {
1387                                this.scribe.space();
1388                            }
1389                            int length = typeArguments.length;
1390                            for (int j = 0; j < length - 1; j++) {
1391                                typeArguments[j].traverse(this, scope);
1392                                this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_type_arguments);
1393                                if (this.preferences.insert_space_after_comma_in_type_arguments) {
1394                                    this.scribe.space();
1395                                }
1396                            }
1397                            typeArguments[length - 1].traverse(this, scope);
1398                            if (isClosingGenericToken()) {
1399                                this.scribe.printNextToken(CLOSING_GENERICS_EXPECTEDTOKENS, this.preferences.insert_space_before_closing_angle_bracket_in_type_arguments);
1400                            }
1401                            if (this.preferences.insert_space_after_closing_angle_bracket_in_type_arguments) {
1402                                this.scribe.space();
1403                            }
1404                    }
1405                    ASTNode[] arguments = currentMessageSend.arguments;
1406                    this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier); // selector
1407
this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_method_invocation);
1408                    if (arguments != null) {
1409                        if (this.preferences.insert_space_after_opening_paren_in_method_invocation) {
1410                            this.scribe.space();
1411                        }
1412                        int argumentLength = arguments.length;
1413                        Alignment argumentsAlignment = this.scribe.createAlignment(
1414                                "messageArguments", //$NON-NLS-1$
1415
this.preferences.alignment_for_arguments_in_method_invocation,
1416                                Alignment.R_OUTERMOST,
1417                                argumentLength,
1418                                this.scribe.scanner.currentPosition);
1419                        this.scribe.enterAlignment(argumentsAlignment);
1420                        boolean okForArguments = false;
1421                        do {
1422                            try {
1423                                for (int j = 0; j < argumentLength; j++) {
1424                                    if (j > 0) {
1425                                        this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_method_invocation_arguments);
1426                                        this.scribe.printTrailingComment();
1427                                    }
1428                                    this.scribe.alignFragment(argumentsAlignment, j);
1429                                    if (j > 0 && this.preferences.insert_space_after_comma_in_method_invocation_arguments) {
1430                                        this.scribe.space();
1431                                    }
1432                                    arguments[j].traverse(this, scope);
1433                                }
1434                                okForArguments = true;
1435                            } catch (AlignmentException e) {
1436                                this.scribe.redoAlignment(e);
1437                            }
1438                        } while (!okForArguments);
1439                        this.scribe.exitAlignment(argumentsAlignment, true);
1440                        this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_method_invocation);
1441                    } else {
1442                        this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_between_empty_parens_in_method_invocation);
1443                    }
1444                    if (numberOfParens > 0) {
1445                        manageClosingParenthesizedExpression(currentMessageSend, numberOfParens);
1446                    }
1447                    if (i < size - 1) {
1448                        this.scribe.alignFragment(cascadingMessageSendAlignment, i);
1449                        this.scribe.printNextToken(TerminalTokens.TokenNameDOT);
1450                    }
1451                }
1452                ok = true;
1453            } catch(AlignmentException e){
1454                this.scribe.redoAlignment(e);
1455            }
1456        } while (!ok);
1457        this.scribe.exitAlignment(cascadingMessageSendAlignment, true);
1458    }
1459    
1460    /*
1461     * Merged traversal of member (types, fields, methods)
1462     */

1463    private void formatClassBodyDeclarations(ASTNode[] nodes) {
1464        final int FIELD = 1, METHOD = 2, TYPE = 3;
1465        this.scribe.lastNumberOfNewLines = 1;
1466        ASTNode[] mergedNodes = computeMergedMemberDeclarations(nodes);
1467        Alignment memberAlignment = this.scribe.createMemberAlignment("typeMembers", this.preferences.align_type_members_on_columns ? Alignment.M_MULTICOLUMN : Alignment.M_NO_ALIGNMENT, 4, this.scribe.scanner.currentPosition); //$NON-NLS-1$
1468
this.scribe.enterMemberAlignment(memberAlignment);
1469        boolean isChunkStart = false;
1470        boolean ok = false;
1471        int startIndex = 0;
1472        do {
1473            try {
1474                for (int i = startIndex, max = mergedNodes.length; i < max; i++) {
1475                    ASTNode member = mergedNodes[i];
1476                    if (member instanceof FieldDeclaration) {
1477                        isChunkStart = memberAlignment.checkChunkStart(FIELD, i, this.scribe.scanner.currentPosition);
1478                        if (member instanceof MultiFieldDeclaration){
1479                            MultiFieldDeclaration multiField = (MultiFieldDeclaration) member;
1480                            format(multiField, this, null, isChunkStart, i == 0);
1481                        } else if (member instanceof Initializer) {
1482                            int newLineBeforeChunk = isChunkStart ? this.preferences.blank_lines_before_new_chunk : 0;
1483                            if (newLineBeforeChunk > 0 && i != 0) {
1484                                this.scribe.printEmptyLines(newLineBeforeChunk);
1485                            } else if (i == 0) {
1486                                int newLinesBeforeFirstClassBodyDeclaration = this.preferences.blank_lines_before_first_class_body_declaration;
1487                                if (newLinesBeforeFirstClassBodyDeclaration > 0) {
1488                                    this.scribe.printEmptyLines(newLinesBeforeFirstClassBodyDeclaration);
1489                                }
1490                            }
1491                            Initializer initializer = (Initializer) member;
1492                            initializer.traverse(this, null);
1493                        } else {
1494                            FieldDeclaration field = (FieldDeclaration) member;
1495                            format(field, this, null, isChunkStart, i == 0);
1496                        }
1497                    } else if (member instanceof AbstractMethodDeclaration) {
1498                        isChunkStart = memberAlignment.checkChunkStart(METHOD, i, this.scribe.scanner.currentPosition);
1499                        format((AbstractMethodDeclaration) member, null, isChunkStart, i == 0);
1500                    } else {
1501                        isChunkStart = memberAlignment.checkChunkStart(TYPE, i, this.scribe.scanner.currentPosition);
1502                        format((TypeDeclaration)member, null, isChunkStart, i == 0);
1503                    }
1504                    if (isNextToken(TerminalTokens.TokenNameSEMICOLON)) {
1505                        this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
1506                        this.scribe.printTrailingComment();
1507                    }
1508                    if (i != max - 1) {
1509                        this.scribe.printNewLine();
1510                    }
1511                }
1512                ok = true;
1513            } catch(AlignmentException e){
1514                startIndex = memberAlignment.chunkStartIndex;
1515                this.scribe.redoMemberAlignment(e);
1516            }
1517        } while (!ok);
1518        this.scribe.exitMemberAlignment(memberAlignment);
1519        if (hasComments()) {
1520            this.scribe.printNewLine();
1521        }
1522        this.scribe.printComment();
1523    }
1524
1525    private void formatEmptyTypeDeclaration(boolean isFirst) {
1526        boolean hasSemiColon = isNextToken(TerminalTokens.TokenNameSEMICOLON);
1527        while(isNextToken(TerminalTokens.TokenNameSEMICOLON)) {
1528            this.scribe.printComment();
1529            this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
1530            this.scribe.printTrailingComment();
1531        }
1532        if (hasSemiColon && isFirst) {
1533            this.scribe.printNewLine();
1534        }
1535    }
1536
1537    private void formatGuardClauseBlock(Block block, BlockScope scope) {
1538
1539        this.scribe.printNextToken(TerminalTokens.TokenNameLBRACE, this.preferences.insert_space_before_opening_brace_in_block);
1540        this.scribe.space();
1541
1542        final Statement[] statements = block.statements;
1543        statements[0].traverse(this, scope);
1544        this.scribe.printNextToken(TerminalTokens.TokenNameRBRACE, true);
1545        this.scribe.printTrailingComment();
1546    }
1547
1548    private void formatLeftCurlyBrace(final int line, final String JavaDoc bracePosition) {
1549        /*
1550         * deal with (quite unexpected) comments right before lcurly
1551         */

1552        this.scribe.printComment();
1553        if (DefaultCodeFormatterConstants.NEXT_LINE_ON_WRAP.equals(bracePosition)
1554                && (this.scribe.line > line || this.scribe.column >= this.preferences.page_width))
1555        {
1556            this.scribe.printNewLine();
1557        }
1558    }
1559    
1560    private void formatLocalDeclaration(LocalDeclaration localDeclaration, BlockScope scope, boolean insertSpaceBeforeComma, boolean insertSpaceAfterComma) {
1561
1562        if (!isMultipleLocalDeclaration(localDeclaration)) {
1563            if (localDeclaration.modifiers != NO_MODIFIERS || localDeclaration.annotations != null) {
1564                this.scribe.printComment();
1565                this.scribe.printModifiers(localDeclaration.annotations, this);
1566                this.scribe.space();
1567            }
1568    
1569            /*
1570             * Argument type
1571             */

1572            if (localDeclaration.type != null) {
1573                localDeclaration.type.traverse(this, scope);
1574            }
1575            /*
1576             * Print the argument name
1577            */

1578            this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, true);
1579        } else {
1580            /*
1581             * Print the argument name
1582            */

1583            this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, false);
1584        }
1585        /*
1586         * Check for extra dimensions
1587         */

1588        int extraDimensions = getDimensions();
1589        if (extraDimensions != 0) {
1590             for (int index = 0; index < extraDimensions; index++) {
1591                this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET);
1592                this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET);
1593             }
1594        }
1595    
1596        final Expression initialization = localDeclaration.initialization;
1597        if (initialization != null) {
1598            /*
1599             * Print the method name
1600             */

1601            this.scribe.printNextToken(TerminalTokens.TokenNameEQUAL, this.preferences.insert_space_before_assignment_operator);
1602            if (this.preferences.insert_space_after_assignment_operator) {
1603                this.scribe.space();
1604            }
1605            Alignment assignmentAlignment = this.scribe.createAlignment("localDeclarationAssignmentAlignment", this.preferences.alignment_for_assignment, Alignment.R_OUTERMOST, 1, this.scribe.scanner.currentPosition); //$NON-NLS-1$
1606
this.scribe.enterAlignment(assignmentAlignment);
1607            boolean ok = false;
1608            do {
1609                try {
1610                    this.scribe.alignFragment(assignmentAlignment, 0);
1611                    initialization.traverse(this, scope);
1612                    ok = true;
1613                } catch(AlignmentException e){
1614                    this.scribe.redoAlignment(e);
1615                }
1616            } while (!ok);
1617            this.scribe.exitAlignment(assignmentAlignment, true);
1618        }
1619
1620        if (isPartOfMultipleLocalDeclaration()) {
1621            this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, insertSpaceBeforeComma);
1622            if (insertSpaceAfterComma) {
1623                this.scribe.space();
1624            }
1625            this.scribe.printTrailingComment();
1626        }
1627    }
1628
1629    private void formatMessageSend(
1630        MessageSend messageSend,
1631        BlockScope scope,
1632        Alignment messageAlignment) {
1633
1634        if (messageAlignment != null) {
1635            this.scribe.alignFragment(messageAlignment, 0);
1636            this.scribe.printNextToken(TerminalTokens.TokenNameDOT);
1637        }
1638        TypeReference[] typeArguments = messageSend.typeArguments;
1639        if (typeArguments != null) {
1640                this.scribe.printNextToken(TerminalTokens.TokenNameLESS, this.preferences.insert_space_before_opening_angle_bracket_in_type_arguments);
1641                if (this.preferences.insert_space_after_opening_angle_bracket_in_type_arguments) {
1642                    this.scribe.space();
1643                }
1644                int length = typeArguments.length;
1645                for (int i = 0; i < length - 1; i++) {
1646                    typeArguments[i].traverse(this, scope);
1647                    this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_type_arguments);
1648                    if (this.preferences.insert_space_after_comma_in_type_arguments) {
1649                        this.scribe.space();
1650                    }
1651                }
1652                typeArguments[length - 1].traverse(this, scope);
1653                if (isClosingGenericToken()) {
1654                    this.scribe.printNextToken(CLOSING_GENERICS_EXPECTEDTOKENS, this.preferences.insert_space_before_closing_angle_bracket_in_type_arguments);
1655                }
1656                if (this.preferences.insert_space_after_closing_angle_bracket_in_type_arguments) {
1657                    this.scribe.space();
1658                }
1659        }
1660        this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier); // selector
1661
this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_method_invocation);
1662
1663        final Expression[] arguments = messageSend.arguments;
1664        if (arguments != null) {
1665            if (this.preferences.insert_space_after_opening_paren_in_method_invocation) {
1666                this.scribe.space();
1667            }
1668            int argumentsLength = arguments.length;
1669            if (argumentsLength > 1) {
1670                Alignment argumentsAlignment = this.scribe.createAlignment(
1671                        "messageArguments", //$NON-NLS-1$
1672
this.preferences.alignment_for_arguments_in_method_invocation,
1673                        argumentsLength,
1674                        this.scribe.scanner.currentPosition);
1675                this.scribe.enterAlignment(argumentsAlignment);
1676                boolean ok = false;
1677                do {
1678                    try {
1679                        for (int i = 0; i < argumentsLength; i++) {
1680                            if (i > 0) {
1681                                this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_method_invocation_arguments);
1682                                this.scribe.printTrailingComment();
1683                            }
1684                            this.scribe.alignFragment(argumentsAlignment, i);
1685                            if (i > 0 && this.preferences.insert_space_after_comma_in_method_invocation_arguments) {
1686                                this.scribe.space();
1687                            }
1688                            arguments[i].traverse(this, scope);
1689                        }
1690                        ok = true;
1691                    } catch (AlignmentException e) {
1692                        this.scribe.redoAlignment(e);
1693                    }
1694                } while (!ok);
1695                this.scribe.exitAlignment(argumentsAlignment, true);
1696            } else {
1697                for (int i = 0; i < argumentsLength; i++) {
1698                    if (i > 0) {
1699                        this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_method_invocation_arguments);
1700                        this.scribe.printTrailingComment();
1701                    }
1702                    if (i > 0 && this.preferences.insert_space_after_comma_in_method_invocation_arguments) {
1703                        this.scribe.space();
1704                    }
1705                    arguments[i].traverse(this, scope);
1706                }
1707            }
1708            this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_method_invocation);
1709        } else {
1710            this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_between_empty_parens_in_method_invocation);
1711        }
1712    }
1713
1714    private void formatMethodArguments(
1715            AbstractMethodDeclaration methodDeclaration,
1716            boolean spaceBeforeOpenParen,
1717            boolean spaceBetweenEmptyParameters,
1718            boolean spaceBeforeClosingParen,
1719            boolean spaceBeforeFirstParameter,
1720            boolean spaceBeforeComma,
1721            boolean spaceAfterComma,
1722            int methodDeclarationParametersAlignment) {
1723                
1724        this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, spaceBeforeOpenParen);
1725        
1726        final Argument[] arguments = methodDeclaration.arguments;
1727        if (arguments != null) {
1728            if (spaceBeforeFirstParameter) {
1729                this.scribe.space();
1730            }
1731            int argumentLength = arguments.length;
1732            Alignment argumentsAlignment = this.scribe.createAlignment(
1733                    "methodArguments",//$NON-NLS-1$
1734
methodDeclarationParametersAlignment,
1735                    argumentLength,
1736                    this.scribe.scanner.currentPosition);
1737            this.scribe.enterAlignment(argumentsAlignment);
1738            boolean ok = false;
1739            do {
1740                try {
1741                    for (int i = 0; i < argumentLength; i++) {
1742                        if (i > 0) {
1743                            this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, spaceBeforeComma);
1744                            this.scribe.printTrailingComment();
1745                        }
1746                        this.scribe.alignFragment(argumentsAlignment, i);
1747                        if (i > 0 && spaceAfterComma) {
1748                            this.scribe.space();
1749                        }
1750                        arguments[i].traverse(this, methodDeclaration.scope);
1751                    }
1752                    ok = true;
1753                } catch (AlignmentException e) {
1754                    this.scribe.redoAlignment(e);
1755                }
1756            } while (!ok);
1757            this.scribe.exitAlignment(argumentsAlignment, true);
1758        
1759            this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, spaceBeforeClosingParen);
1760        } else {
1761            this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, spaceBetweenEmptyParameters);
1762        }
1763    }
1764
1765    private void formatEnumConstantArguments(
1766            FieldDeclaration enumConstant,
1767            boolean spaceBeforeOpenParen,
1768            boolean spaceBetweenEmptyParameters,
1769            boolean spaceBeforeClosingParen,
1770            boolean spaceBeforeFirstParameter,
1771            boolean spaceBeforeComma,
1772            boolean spaceAfterComma,
1773            int methodDeclarationParametersAlignment) {
1774                
1775        if (!isNextToken(TerminalTokens.TokenNameLPAREN)) {
1776            return;
1777        }
1778        
1779        this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, spaceBeforeOpenParen);
1780        final Expression[] arguments = ((AllocationExpression) enumConstant.initialization).arguments;
1781        if (arguments != null) {
1782            int argumentLength = arguments.length;
1783            Alignment argumentsAlignment = this.scribe.createAlignment(
1784                    "enumConstantArguments",//$NON-NLS-1$
1785
methodDeclarationParametersAlignment,
1786                    argumentLength,
1787                    this.scribe.scanner.currentPosition);
1788            this.scribe.enterAlignment(argumentsAlignment);
1789            boolean ok = false;
1790            do {
1791                try {
1792                    if (spaceBeforeFirstParameter) {
1793                        this.scribe.space();
1794                    }
1795                    for (int i = 0; i < argumentLength; i++) {
1796                        if (i > 0) {
1797                            this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, spaceBeforeComma);
1798                            this.scribe.printTrailingComment();
1799                        }
1800                        this.scribe.alignFragment(argumentsAlignment, i);
1801                        if (i > 0 && spaceAfterComma) {
1802                            this.scribe.space();
1803                        }
1804                        arguments[i].traverse(this, (BlockScope) null);
1805                    }
1806                    ok = true;
1807                } catch (AlignmentException e) {
1808                    this.scribe.redoAlignment(e);
1809                }
1810            } while (!ok);
1811            this.scribe.exitAlignment(argumentsAlignment, true);
1812        
1813            this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, spaceBeforeClosingParen);
1814        } else {
1815            this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, spaceBetweenEmptyParameters);
1816        }
1817    }
1818
1819    private void formatNecessaryEmptyStatement() {
1820        if (this.preferences.put_empty_statement_on_new_line) {
1821            this.scribe.printNewLine();
1822            this.scribe.indent();
1823            this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
1824            this.scribe.printTrailingComment();
1825            this.scribe.unIndent();
1826        } else {
1827            this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
1828            this.scribe.printTrailingComment();
1829        }
1830    }
1831    
1832    private void formatOpeningBrace(String JavaDoc bracePosition, boolean insertSpaceBeforeBrace) {
1833    
1834        if (DefaultCodeFormatterConstants.NEXT_LINE.equals(bracePosition)) {
1835            this.scribe.printNewLine();
1836        } else if (DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED.equals(bracePosition)) {
1837            this.scribe.printNewLine();
1838            this.scribe.indent();
1839        }
1840        this.scribe.printNextToken(TerminalTokens.TokenNameLBRACE, insertSpaceBeforeBrace);
1841
1842        this.scribe.printTrailingComment();
1843    }
1844    private void formatStatements(BlockScope scope, final Statement[] statements, boolean insertNewLineAfterLastStatement) {
1845        int statementsLength = statements.length;
1846        for (int i = 0; i < statementsLength; i++) {
1847            final Statement statement = statements[i];
1848            if (i > 0 && (statements[i - 1] instanceof EmptyStatement) && !(statement instanceof EmptyStatement)) {
1849                this.scribe.printNewLine();
1850            }
1851            statement.traverse(this, scope);
1852            if (statement instanceof Expression) {
1853                this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
1854                this.scribe.printTrailingComment();
1855                if (i != statementsLength - 1) {
1856                    if (!(statement instanceof EmptyStatement) && !(statements[i + 1] instanceof EmptyStatement)) {
1857                        this.scribe.printNewLine();
1858                    }
1859                } else if (i == statementsLength - 1 && insertNewLineAfterLastStatement) {
1860                    this.scribe.printNewLine();
1861                }
1862            } else if (statement instanceof LocalDeclaration) {
1863                LocalDeclaration currentLocal = (LocalDeclaration) statement;
1864                if (i < (statementsLength - 1)) {
1865                    /*
1866                     * We need to check that the next statement is a local declaration
1867                     */

1868                    if (statements[i + 1] instanceof LocalDeclaration) {
1869                        LocalDeclaration nextLocal = (LocalDeclaration) statements[i + 1];
1870                        if (currentLocal.declarationSourceStart != nextLocal.declarationSourceStart) {
1871                            this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
1872                            this.scribe.printTrailingComment();
1873                            if (i != statementsLength - 1) {
1874                                if (!(statement instanceof EmptyStatement) && !(statements[i + 1] instanceof EmptyStatement)) {
1875                                    this.scribe.printNewLine();
1876                                }
1877                            } else if (i == statementsLength - 1 && insertNewLineAfterLastStatement) {
1878                                this.scribe.printNewLine();
1879                            }
1880                        }
1881                    } else {
1882                        this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
1883                        this.scribe.printTrailingComment();
1884                        if (i != statementsLength - 1) {
1885                            if (!(statement instanceof EmptyStatement) && !(statements[i + 1] instanceof EmptyStatement)) {
1886                                this.scribe.printNewLine();
1887                            }
1888                        } else if (i == statementsLength - 1 && insertNewLineAfterLastStatement) {
1889                            this.scribe.printNewLine();
1890                        }
1891                    }
1892                } else {
1893                    this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
1894                    this.scribe.printTrailingComment();
1895                    if (i != statementsLength - 1) {
1896                        if (!(statement instanceof EmptyStatement) && !(statements[i + 1] instanceof EmptyStatement)) {
1897                            this.scribe.printNewLine();
1898                        }
1899                    } else if (i == statementsLength - 1 && insertNewLineAfterLastStatement) {
1900                        this.scribe.printNewLine();
1901                    }
1902                }
1903            } else if (i != statementsLength - 1) {
1904                if (!(statement instanceof EmptyStatement) && !(statements[i + 1] instanceof EmptyStatement)) {
1905                    this.scribe.printNewLine();
1906                }
1907            } else if (i == statementsLength - 1 && insertNewLineAfterLastStatement) {
1908                this.scribe.printNewLine();
1909            }
1910        }
1911    }
1912    
1913    private void formatThrowsClause(
1914        AbstractMethodDeclaration methodDeclaration,
1915        boolean spaceBeforeComma,
1916        boolean spaceAfterComma,
1917        int alignmentForThrowsClause) {
1918            
1919        final TypeReference[] thrownExceptions = methodDeclaration.thrownExceptions;
1920        if (thrownExceptions != null) {
1921            int thrownExceptionsLength = thrownExceptions.length;
1922            Alignment throwsAlignment = this.scribe.createAlignment(
1923                    "throws",//$NON-NLS-1$
1924
alignmentForThrowsClause,
1925                    thrownExceptionsLength, // throws is the first token
1926
this.scribe.scanner.currentPosition);
1927        
1928            this.scribe.enterAlignment(throwsAlignment);
1929            boolean ok = false;
1930            do {
1931                try {
1932                    this.scribe.alignFragment(throwsAlignment, 0);
1933                    this.scribe.printNextToken(TerminalTokens.TokenNamethrows, true);
1934        
1935                    for (int i = 0; i < thrownExceptionsLength; i++) {
1936                        if (i > 0) {
1937                            this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, spaceBeforeComma);
1938                            this.scribe.printTrailingComment();
1939                            this.scribe.alignFragment(throwsAlignment, i);
1940                            if (spaceAfterComma) {
1941                                this.scribe.space();
1942                            }
1943                        } else {
1944                            this.scribe.space();
1945                        }
1946                        thrownExceptions[i].traverse(this, methodDeclaration.scope);
1947                    }
1948                    ok = true;
1949                } catch (AlignmentException e) {
1950                    this.scribe.redoAlignment(e);
1951                }
1952            } while (!ok);
1953            this.scribe.exitAlignment(throwsAlignment, true);
1954        }
1955    }
1956
1957    /*
1958     * Merged traversal of member (types, fields, methods)
1959     */

1960    private void formatTypeMembers(TypeDeclaration typeDeclaration) {
1961        Alignment 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$
1962
this.scribe.enterMemberAlignment(memberAlignment);
1963        ASTNode[] members = computeMergedMemberDeclarations(typeDeclaration);
1964        boolean isChunkStart = false;
1965        boolean ok = false;
1966        int startIndex = 0;
1967        do {
1968            try {
1969                for (int i = startIndex, max = members.length; i < max; i++) {
1970                    ASTNode member = members[i];
1971                    if (member instanceof FieldDeclaration) {
1972                        isChunkStart = memberAlignment.checkChunkStart(Alignment.CHUNK_FIELD, i, this.scribe.scanner.currentPosition);
1973                        if (member instanceof MultiFieldDeclaration) {
1974                            MultiFieldDeclaration multiField = (MultiFieldDeclaration) member;
1975                            
1976                            if (multiField.isStatic()) {
1977                                format(multiField, this, typeDeclaration.staticInitializerScope, isChunkStart, i == 0);
1978                            } else {
1979                                format(multiField, this, typeDeclaration.initializerScope, isChunkStart, i == 0);
1980                            }
1981                        } else if (member instanceof Initializer) {
1982                            int newLineBeforeChunk = isChunkStart ? this.preferences.blank_lines_before_new_chunk : 0;
1983                            if (newLineBeforeChunk > 0 && i != 0) {
1984                                this.scribe.printEmptyLines(newLineBeforeChunk);
1985                            } else if (i == 0) {
1986                                int newLinesBeforeFirstClassBodyDeclaration = this.preferences.blank_lines_before_first_class_body_declaration;
1987                                if (newLinesBeforeFirstClassBodyDeclaration > 0) {
1988                                    this.scribe.printEmptyLines(newLinesBeforeFirstClassBodyDeclaration);
1989                                }
1990                            }
1991                            Initializer initializer = (Initializer) member;
1992                            if (initializer.isStatic()) {
1993                                initializer.traverse(this, typeDeclaration.staticInitializerScope);
1994                            } else {
1995                                initializer.traverse(this, typeDeclaration.initializerScope);
1996                            }
1997                        } else {
1998                            FieldDeclaration field = (FieldDeclaration) member;
1999                            if (field.isStatic()) {
2000                                format(field, this, typeDeclaration.staticInitializerScope, isChunkStart, i == 0);
2001                            } else {
2002                                format(field, this, typeDeclaration.initializerScope, isChunkStart, i == 0);
2003                            }
2004                        }
2005                    } else if (member instanceof AbstractMethodDeclaration) {
2006                        isChunkStart = memberAlignment.checkChunkStart(Alignment.CHUNK_METHOD, i, this.scribe.scanner.currentPosition);
2007                        format((AbstractMethodDeclaration) member, typeDeclaration.scope, isChunkStart, i == 0);
2008                    } else if (member instanceof TypeDeclaration) {
2009                        isChunkStart = memberAlignment.checkChunkStart(Alignment.CHUNK_TYPE, i, this.scribe.scanner.currentPosition);
2010                        format((TypeDeclaration)member, typeDeclaration.scope, isChunkStart, i == 0);
2011                    }
2012                    if (isNextToken(TerminalTokens.TokenNameSEMICOLON)) {
2013                        this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
2014                        this.scribe.printTrailingComment();
2015                    }
2016                    this.scribe.printNewLine();
2017                    // realign to the proper value
2018
if (this.scribe.memberAlignment != null) {
2019                        // select the last alignment
2020
this.scribe.indentationLevel = this.scribe.memberAlignment.originalIndentationLevel;
2021                    }
2022                }
2023                ok = true;
2024            } catch(AlignmentException e){
2025                startIndex = memberAlignment.chunkStartIndex;
2026                this.scribe.redoMemberAlignment(e);
2027            }
2028        } while (!ok);
2029        this.scribe.printComment();
2030        this.scribe.exitMemberAlignment(memberAlignment);
2031    }
2032
2033    private void formatTypeOpeningBraceForEnumConstant(String JavaDoc bracePosition, boolean insertSpaceBeforeBrace, TypeDeclaration typeDeclaration) {
2034        int fieldCount = (typeDeclaration.fields == null) ? 0 : typeDeclaration.fields.length;
2035        int methodCount = (typeDeclaration.methods == null) ? 0 : typeDeclaration.methods.length;
2036        int typeCount = (typeDeclaration.memberTypes == null) ? 0 : typeDeclaration.memberTypes.length;
2037    
2038        if (methodCount <= 2) {
2039            for (int i = 0, max = methodCount; i < max; i++) {
2040                final AbstractMethodDeclaration abstractMethodDeclaration = typeDeclaration.methods[i];
2041                if (abstractMethodDeclaration.isDefaultConstructor()) {
2042                    methodCount--;
2043                } else if (abstractMethodDeclaration.isClinit()) {
2044                    methodCount--;
2045                }
2046            }
2047        }
2048        final int memberLength = fieldCount + methodCount+typeCount;
2049
2050        boolean insertNewLine = memberLength > 0;
2051        
2052        if (!insertNewLine) {
2053            if ((typeDeclaration.bits & ASTNode.IsAnonymousType) != 0) {
2054                insertNewLine = this.preferences.insert_new_line_in_empty_enum_constant;
2055            }
2056        }
2057    
2058        formatOpeningBrace(bracePosition, insertSpaceBeforeBrace);
2059        
2060        if (insertNewLine) {
2061            this.scribe.printNewLine();
2062        }
2063    }
2064    private void formatTypeOpeningBrace(String JavaDoc bracePosition, boolean insertSpaceBeforeBrace, TypeDeclaration typeDeclaration) {
2065        int fieldCount = (typeDeclaration.fields == null) ? 0 : typeDeclaration.fields.length;
2066        int methodCount = (typeDeclaration.methods == null) ? 0 : typeDeclaration.methods.length;
2067        int typeCount = (typeDeclaration.memberTypes == null) ? 0 : typeDeclaration.memberTypes.length;
2068    
2069        if (methodCount <= 2) {
2070            for (int i = 0, max = methodCount; i < max; i++) {
2071                final AbstractMethodDeclaration abstractMethodDeclaration = typeDeclaration.methods[i];
2072                if (abstractMethodDeclaration.isDefaultConstructor()) {
2073                    methodCount--;
2074                } else if (abstractMethodDeclaration.isClinit()) {
2075                    methodCount--;
2076                }
2077            }
2078        }
2079        final int memberLength = fieldCount + methodCount + typeCount;
2080
2081        boolean insertNewLine = memberLength > 0;
2082        
2083        if (!insertNewLine) {
2084            if (TypeDeclaration.kind(typeDeclaration.modifiers) == TypeDeclaration.ENUM_DECL) {
2085                insertNewLine = this.preferences.insert_new_line_in_empty_enum_declaration;
2086            } else if ((typeDeclaration.bits & ASTNode.IsAnonymousType) != 0) {
2087                insertNewLine = this.preferences.insert_new_line_in_empty_anonymous_type_declaration;
2088            } else if (TypeDeclaration.kind(typeDeclaration.modifiers) == TypeDeclaration.ANNOTATION_TYPE_DECL) {
2089                insertNewLine = this.preferences.insert_new_line_in_empty_annotation_declaration;
2090            } else {
2091                insertNewLine = this.preferences.insert_new_line_in_empty_type_declaration;
2092            }
2093        }
2094    
2095        formatOpeningBrace(bracePosition, insertSpaceBeforeBrace);
2096        
2097        if (insertNewLine) {
2098            this.scribe.printNewLine();
2099        }
2100    }
2101    private int getDimensions() {
2102
2103        this.localScanner.resetTo(this.scribe.scanner.currentPosition, this.scribe.scannerEndPosition - 1);
2104        int dimensions = 0;
2105        int balance = 0;
2106        try {
2107            int token;
2108            loop: while ((token = this.localScanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
2109                switch(token) {
2110                    case TerminalTokens.TokenNameRBRACKET:
2111                        dimensions++;
2112                        balance--;
2113                        break;
2114                    case TerminalTokens.TokenNameCOMMENT_BLOCK :
2115                    case TerminalTokens.TokenNameCOMMENT_JAVADOC :
2116                    case TerminalTokens.TokenNameCOMMENT_LINE :
2117                        break;
2118                    case TerminalTokens.TokenNameLBRACKET :
2119                        balance++;
2120                        break;
2121                    default:
2122                        break loop;
2123                }
2124            }
2125        } catch(InvalidInputException e) {
2126            // ignore
2127
}
2128        if (balance == 0) {
2129            return dimensions;
2130        }
2131        return 0;
2132    }
2133
2134    private boolean hasComments() {
2135
2136        this.localScanner.resetTo(this.scribe.scanner.startPosition, this.scribe.scannerEndPosition - 1);
2137        try {
2138            switch(this.localScanner.getNextToken()) {
2139                case TerminalTokens.TokenNameCOMMENT_BLOCK :
2140                case TerminalTokens.TokenNameCOMMENT_JAVADOC :
2141                case TerminalTokens.TokenNameCOMMENT_LINE :
2142                    return true;
2143            }
2144        } catch(InvalidInputException e) {
2145            // ignore
2146
}
2147        return false;
2148    }
2149
2150    private boolean isNextToken(int tokenName) {
2151        this.localScanner.resetTo(this.scribe.scanner.currentPosition, this.scribe.scannerEndPosition - 1);
2152        try {
2153            int token = this.localScanner.getNextToken();
2154            loop: while(true) {
2155                switch(token) {
2156                    case TerminalTokens.TokenNameCOMMENT_BLOCK :
2157                    case TerminalTokens.TokenNameCOMMENT_JAVADOC :
2158                    case TerminalTokens.TokenNameCOMMENT_LINE :
2159                        token = this.localScanner.getNextToken();
2160                        continue loop;
2161                    default:
2162                        break loop;
2163                }
2164            }
2165            return token == tokenName;
2166        } catch(InvalidInputException e) {
2167            // ignore
2168
}
2169        return false;
2170    }
2171
2172    private boolean isClosingGenericToken() {
2173        this.localScanner.resetTo(this.scribe.scanner.currentPosition, this.scribe.scannerEndPosition - 1);
2174        try {
2175            int token = this.localScanner.getNextToken();
2176            loop: while(true) {
2177                switch(token) {
2178                    case TerminalTokens.TokenNameCOMMENT_BLOCK :
2179                    case TerminalTokens.TokenNameCOMMENT_JAVADOC :
2180                    case TerminalTokens.TokenNameCOMMENT_LINE :
2181                        token = this.localScanner.getNextToken();
2182                        continue loop;
2183                    default:
2184                        break loop;
2185                }
2186            }
2187            switch(token) {
2188                case TerminalTokens.TokenNameGREATER :
2189                case TerminalTokens.TokenNameRIGHT_SHIFT :
2190                case TerminalTokens.TokenNameUNSIGNED_RIGHT_SHIFT :
2191                    return true;
2192            }
2193        } catch(InvalidInputException e) {
2194            // ignore
2195
}
2196        return false;
2197    }
2198
2199    private boolean isGuardClause(Block block) {
2200        return !commentStartsBlock(block.sourceStart, block.sourceEnd)
2201                && block.statements != null
2202                && block.statements.length == 1
2203                && (block.statements[0] instanceof ReturnStatement || block.statements[0] instanceof ThrowStatement);
2204    }
2205
2206    private boolean isMultipleLocalDeclaration(LocalDeclaration localDeclaration) {
2207
2208        if (localDeclaration.declarationSourceStart == this.lastLocalDeclarationSourceStart) return true;
2209        this.lastLocalDeclarationSourceStart = localDeclaration.declarationSourceStart;
2210        return false;
2211    }
2212
2213    private boolean isPartOfMultipleLocalDeclaration() {
2214        this.localScanner.resetTo(this.scribe.scanner.currentPosition, this.scribe.scannerEndPosition - 1);
2215        try {
2216            int token;
2217            while ((token = this.localScanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
2218                switch(token) {
2219                    case TerminalTokens.TokenNameCOMMA ://90
2220
return true;
2221                    case TerminalTokens.TokenNameCOMMENT_BLOCK :
2222                    case TerminalTokens.TokenNameCOMMENT_JAVADOC :
2223                    case TerminalTokens.TokenNameCOMMENT_LINE :
2224                        break;
2225                    default:
2226                        return false;
2227                }
2228            }
2229        } catch(InvalidInputException e) {
2230            // ignore
2231
}
2232        return false;
2233    }
2234
2235    private void manageClosingParenthesizedExpression(Expression expression, int numberOfParens) {
2236        for (int i = 0; i < numberOfParens; i++) {
2237            this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_parenthesized_expression);
2238        }
2239    }
2240
2241    private void manageOpeningParenthesizedExpression(Expression expression, int numberOfParens) {
2242        for (int i = 0; i < numberOfParens; i++) {
2243            this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_parenthesized_expression);
2244            if (this.preferences.insert_space_after_opening_paren_in_parenthesized_expression) {
2245                this.scribe.space();
2246            }
2247        }
2248    }
2249            
2250    /**
2251     * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.AllocationExpression, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
2252     */

2253    public boolean visit(
2254        AllocationExpression allocationExpression,
2255        BlockScope scope) {
2256        // 'new' ClassType '(' ArgumentListopt ')' ClassBodyopt
2257

2258        final int numberOfParens = (allocationExpression.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
2259        if (numberOfParens > 0) {
2260            manageOpeningParenthesizedExpression(allocationExpression, numberOfParens);
2261        }
2262        this.scribe.printNextToken(TerminalTokens.TokenNamenew);
2263        TypeReference[] typeArguments = allocationExpression.typeArguments;
2264        if (typeArguments != null) {
2265                this.scribe.printNextToken(TerminalTokens.TokenNameLESS, this.preferences.insert_space_before_opening_angle_bracket_in_type_arguments);
2266                if (this.preferences.insert_space_after_opening_angle_bracket_in_type_arguments) {
2267                    this.scribe.space();
2268                }
2269                int length = typeArguments.length;
2270                for (int i = 0; i < length - 1; i++) {
2271                    typeArguments[i].traverse(this, scope);
2272                    this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_type_arguments);
2273                    if (this.preferences.insert_space_after_comma_in_type_arguments) {
2274                        this.scribe.space();
2275                    }
2276                }
2277                typeArguments[length - 1].traverse(this, scope);
2278                if (isClosingGenericToken()) {
2279                    this.scribe.printNextToken(CLOSING_GENERICS_EXPECTEDTOKENS, this.preferences.insert_space_before_closing_angle_bracket_in_type_arguments);
2280                }
2281                if (this.preferences.insert_space_after_closing_angle_bracket_in_type_arguments) {
2282                    this.scribe.space();
2283                }
2284        } else {
2285            this.scribe.space();
2286        }
2287
2288        allocationExpression.type.traverse(this, scope);
2289        
2290        this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_method_invocation);
2291
2292        final Expression[] arguments = allocationExpression.arguments;
2293        if (arguments != null) {
2294            if (this.preferences.insert_space_after_opening_paren_in_method_invocation) {
2295                this.scribe.space();
2296            }
2297            int argumentLength = arguments.length;
2298            Alignment argumentsAlignment =this.scribe.createAlignment(
2299                    "allocation",//$NON-NLS-1$
2300
this.preferences.alignment_for_arguments_in_allocation_expression,
2301                    argumentLength,
2302                    this.scribe.scanner.currentPosition);
2303            this.scribe.enterAlignment(argumentsAlignment);
2304            boolean ok = false;
2305            do {
2306                try {
2307                    for (int i = 0; i < argumentLength; i++) {
2308                        if (i > 0) {
2309                            this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_allocation_expression);
2310                            this.scribe.printTrailingComment();
2311                        }
2312                        this.scribe.alignFragment(argumentsAlignment, i);
2313                        if (i > 0 && this.preferences.insert_space_after_comma_in_allocation_expression) {
2314                            this.scribe.space();
2315                        }
2316                        arguments[i].traverse(this, scope);
2317                    }
2318                    ok = true;
2319                } catch (AlignmentException e) {
2320                    this.scribe.redoAlignment(e);
2321                }
2322            } while (!ok);
2323            this.scribe.exitAlignment(argumentsAlignment, true);
2324            this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_method_invocation);
2325        } else {
2326            this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_between_empty_parens_in_method_invocation);
2327        }
2328        
2329        if (numberOfParens > 0) {
2330            manageClosingParenthesizedExpression(allocationExpression, numberOfParens);
2331        }
2332        return false;
2333    }
2334
2335    /**
2336     * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.AND_AND_Expression, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
2337     */

2338    public boolean visit(
2339        AND_AND_Expression and_and_Expression,
2340        BlockScope scope) {
2341            
2342        return dumpBinaryExpression(and_and_Expression, TerminalTokens.TokenNameAND_AND, scope);
2343    }
2344    public boolean visit(
2345            AnnotationMethodDeclaration annotationTypeMemberDeclaration,
2346            ClassScope scope) {
2347        /*
2348         * Print comments to get proper line number
2349         */

2350        this.scribe.printComment();
2351        this.scribe.printModifiers(annotationTypeMemberDeclaration.annotations, this);
2352        this.scribe.space();
2353        /*
2354         * Print the method return type
2355         */

2356        final TypeReference returnType = annotationTypeMemberDeclaration.returnType;
2357        final MethodScope annotationTypeMemberDeclarationScope = annotationTypeMemberDeclaration.scope;
2358        
2359        if (returnType != null) {
2360            returnType.traverse(this, annotationTypeMemberDeclarationScope);
2361        }
2362        /*
2363         * Print the method name
2364         */

2365        this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, true);
2366        this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_annotation_type_member_declaration);
2367        this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_between_empty_parens_in_annotation_type_member_declaration);
2368
2369        /*
2370         * Check for extra dimensions
2371         */

2372        int extraDimensions = annotationTypeMemberDeclaration.extendedDimensions;
2373        if (extraDimensions != 0) {
2374             for (int i = 0; i < extraDimensions; i++) {
2375                this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET);
2376                this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET);
2377             }
2378        }
2379
2380        Expression defaultValue = annotationTypeMemberDeclaration.defaultValue;
2381        if (defaultValue != null) {
2382            this.scribe.printNextToken(TerminalTokens.TokenNamedefault, true);
2383            this.scribe.space();
2384            defaultValue.traverse(this, (BlockScope) null);
2385        }
2386        this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
2387        this.scribe.printTrailingComment();
2388        return false;
2389    }
2390
2391    /**
2392     * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.Argument, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
2393     */

2394    public boolean visit(Argument argument, BlockScope scope) {
2395
2396        if (argument.modifiers != NO_MODIFIERS || argument.annotations != null) {
2397            this.scribe.printComment();
2398            this.scribe.printModifiers(argument.annotations, this);
2399            this.scribe.space();
2400        }
2401
2402        /*
2403         * Argument type
2404         */

2405        if (argument.type != null) {
2406            argument.type.traverse(this, scope);
2407        }
2408        
2409        if (argument.isVarArgs()) {
2410            this.scribe.printNextToken(TerminalTokens.TokenNameELLIPSIS, this.preferences.insert_space_before_ellipsis);
2411            if (this.preferences.insert_space_after_ellipsis) {
2412                this.scribe.space();
2413            }
2414            this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, false);
2415        } else {
2416            /*
2417             * Print the argument name
2418             */

2419            this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, true);
2420        }
2421
2422
2423        /*
2424         * Check for extra dimensions
2425         */

2426        int extraDimensions = getDimensions();
2427        if (extraDimensions != 0) {
2428             for (int i = 0; i < extraDimensions; i++) {
2429                this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET);
2430                this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET);
2431             }
2432        }
2433        
2434        return false;
2435    }
2436
2437    /**
2438     * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.ArrayAllocationExpression, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
2439     */

2440    public boolean visit(
2441        ArrayAllocationExpression arrayAllocationExpression,
2442        BlockScope scope) {
2443
2444            final int numberOfParens = (arrayAllocationExpression.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
2445            if (numberOfParens > 0) {
2446                manageOpeningParenthesizedExpression(arrayAllocationExpression, numberOfParens);
2447            }
2448            this.scribe.printNextToken(TerminalTokens.TokenNamenew);
2449            this.scribe.space();
2450            arrayAllocationExpression.type.traverse(this, scope);
2451            
2452            final Expression[] dimensions = arrayAllocationExpression.dimensions;
2453            int dimensionsLength = dimensions.length;
2454            for (int i = 0; i < dimensionsLength; i++) {
2455                if (this.preferences.insert_space_before_opening_bracket_in_array_allocation_expression) {
2456                    this.scribe.space();
2457                }
2458                this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET, false);
2459                if (dimensions[i] != null) {
2460                    if (this.preferences.insert_space_after_opening_bracket_in_array_allocation_expression) {
2461                        this.scribe.space();
2462                    }
2463                    dimensions[i].traverse(this, scope);
2464                    this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET, this.preferences.insert_space_before_closing_bracket_in_array_allocation_expression);
2465                } else {
2466                    this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET, this.preferences.insert_space_between_empty_brackets_in_array_allocation_expression);
2467                }
2468            }
2469            final ArrayInitializer initializer = arrayAllocationExpression.initializer;
2470            if (initializer != null) {
2471                initializer.traverse(this, scope);
2472            }
2473
2474            if (numberOfParens > 0) {
2475                manageClosingParenthesizedExpression(arrayAllocationExpression, numberOfParens);
2476            }
2477            return false;
2478    }
2479
2480    /**
2481     * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.ArrayInitializer, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
2482     */

2483    public boolean visit(ArrayInitializer arrayInitializer, BlockScope scope) { final int numberOfParens = (arrayInitializer.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
2484        if (numberOfParens > 0) {
2485            manageOpeningParenthesizedExpression(arrayInitializer, numberOfParens);
2486        }
2487        
2488        final Expression[] expressions = arrayInitializer.expressions;
2489        if (expressions != null) {
2490            String JavaDoc array_initializer_brace_position = this.preferences.brace_position_for_array_initializer;
2491            formatOpeningBrace(array_initializer_brace_position, this.preferences.insert_space_before_opening_brace_in_array_initializer);
2492        
2493            int expressionsLength = expressions.length;
2494            final boolean insert_new_line_after_opening_brace = this.preferences.insert_new_line_after_opening_brace_in_array_initializer;
2495            if (expressionsLength > 1) {
2496                if (insert_new_line_after_opening_brace) {
2497                    this.scribe.printNewLine();
2498                }
2499                Alignment arrayInitializerAlignment =this.scribe.createAlignment(
2500                        "array_initializer",//$NON-NLS-1$
2501
this.preferences.alignment_for_expressions_in_array_initializer,
2502                        Alignment.R_OUTERMOST,
2503                        expressionsLength,
2504                        this.scribe.scanner.currentPosition,
2505                        this.preferences.continuation_indentation_for_array_initializer,
2506                        true);
2507                
2508                if (insert_new_line_after_opening_brace) {
2509                    arrayInitializerAlignment.fragmentIndentations[0] = arrayInitializerAlignment.breakIndentationLevel;
2510                }
2511                
2512                this.scribe.enterAlignment(arrayInitializerAlignment);
2513                boolean ok = false;
2514                do {
2515                    try {
2516                        this.scribe.alignFragment(arrayInitializerAlignment, 0);
2517                        if (this.preferences.insert_space_after_opening_brace_in_array_initializer) {
2518                            this.scribe.space();
2519                        }
2520                        expressions[0].traverse(this, scope);
2521                        for (int i = 1; i < expressionsLength; i++) {
2522                            this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_array_initializer);
2523                            this.scribe.printTrailingComment();
2524                            this.scribe.alignFragment(arrayInitializerAlignment, i);
2525                            if (this.preferences.insert_space_after_comma_in_array_initializer) {
2526                                this.scribe.space();
2527                            }
2528                            expressions[i].traverse(this, scope);
2529                            if (i == expressionsLength - 1) {
2530                                if (isNextToken(TerminalTokens.TokenNameCOMMA)) {
2531                                    this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_array_initializer);
2532                                    this.scribe.printTrailingComment();
2533                                }
2534                            }
2535                        }
2536                        ok = true;
2537                    } catch (AlignmentException e) {
2538                        this.scribe.redoAlignment(e);
2539                    }
2540                } while (!ok);
2541                this.scribe.exitAlignment(arrayInitializerAlignment, true);
2542            } else {
2543                if (insert_new_line_after_opening_brace) {
2544                    this.scribe.printNewLine();
2545                    this.scribe.indent();
2546                }
2547                // we don't need to use an alignment
2548
if (this.preferences.insert_space_after_opening_brace_in_array_initializer) {
2549                    this.scribe.space();
2550                } else {
2551                    this.scribe.needSpace = false;
2552                }
2553                expressions[0].traverse(this, scope);
2554                if (isNextToken(TerminalTokens.TokenNameCOMMA)) {
2555                    this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_array_initializer);
2556                    this.scribe.printTrailingComment();
2557                }
2558                if (insert_new_line_after_opening_brace) {
2559                    this.scribe.unIndent();
2560                }
2561            }
2562            if (this.preferences.insert_new_line_before_closing_brace_in_array_initializer) {
2563                this.scribe.printNewLine();
2564            } else if (this.preferences.insert_space_before_closing_brace_in_array_initializer) {
2565                this.scribe.space();
2566            }
2567            this.scribe.printNextToken(TerminalTokens.TokenNameRBRACE, false);
2568            if (array_initializer_brace_position.equals(DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED)) {
2569                this.scribe.unIndent();
2570            }
2571        } else {
2572            boolean keepEmptyArrayInitializerOnTheSameLine = this.preferences.keep_empty_array_initializer_on_one_line;
2573            String JavaDoc array_initializer_brace_position = this.preferences.brace_position_for_array_initializer;
2574            if (keepEmptyArrayInitializerOnTheSameLine) {
2575                this.scribe.printNextToken(TerminalTokens.TokenNameLBRACE, this.preferences.insert_space_before_opening_brace_in_array_initializer);
2576                this.scribe.printNextToken(TerminalTokens.TokenNameRBRACE, this.preferences.insert_space_between_empty_braces_in_array_initializer);
2577            } else {
2578                formatOpeningBrace(array_initializer_brace_position, this.preferences.insert_space_before_opening_brace_in_array_initializer);
2579                this.scribe.printNextToken(TerminalTokens.TokenNameRBRACE, false);
2580                if (array_initializer_brace_position.equals(DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED)) {
2581                    this.scribe.unIndent();
2582                }
2583            }
2584        }
2585    
2586        if (numberOfParens > 0) {
2587            manageClosingParenthesizedExpression(arrayInitializer, numberOfParens);
2588        }
2589        return false;
2590    }
2591    
2592    /**
2593     * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.ArrayQualifiedTypeReference, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
2594     */

2595    public boolean visit(
2596        ArrayQualifiedTypeReference arrayQualifiedTypeReference,
2597        BlockScope scope) {
2598
2599            final int numberOfParens = (arrayQualifiedTypeReference.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
2600            if (numberOfParens > 0) {
2601                manageOpeningParenthesizedExpression(arrayQualifiedTypeReference, numberOfParens);
2602            }
2603            this.scribe.printArrayQualifiedReference(arrayQualifiedTypeReference.tokens.length, arrayQualifiedTypeReference.sourceEnd);
2604            int dimensions = getDimensions();
2605            if (dimensions != 0) {
2606                for (int i = 0; i < dimensions; i++) {
2607                    this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET);
2608                    this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET);
2609                }
2610            }
2611            if (numberOfParens > 0) {
2612                manageClosingParenthesizedExpression(arrayQualifiedTypeReference, numberOfParens);
2613            }
2614            return false;
2615    }
2616
2617    /**
2618     * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.ArrayQualifiedTypeReference, org.eclipse.jdt.internal.compiler.lookup.ClassScope)
2619     */

2620    public boolean visit(
2621        ArrayQualifiedTypeReference arrayQualifiedTypeReference,
2622        ClassScope scope) {
2623
2624            final int numberOfParens = (arrayQualifiedTypeReference.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
2625            if (numberOfParens > 0) {
2626                manageOpeningParenthesizedExpression(arrayQualifiedTypeReference, numberOfParens);
2627            }
2628            this.scribe.printArrayQualifiedReference(arrayQualifiedTypeReference.tokens.length, arrayQualifiedTypeReference.sourceEnd);
2629            int dimensions = getDimensions();
2630            if (dimensions != 0) {
2631                for (int i = 0; i < dimensions; i++) {
2632                    this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET);
2633                    this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET);
2634                }
2635            }
2636            if (numberOfParens > 0) {
2637                manageClosingParenthesizedExpression(arrayQualifiedTypeReference, numberOfParens);
2638            }
2639            return false;
2640    }
2641
2642
2643    /**
2644     * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.ArrayReference, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
2645     */

2646    public boolean visit(ArrayReference arrayReference, BlockScope scope) {
2647
2648        final int numberOfParens = (arrayReference.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
2649        if (numberOfParens > 0) {
2650            manageOpeningParenthesizedExpression(arrayReference, numberOfParens);
2651        }
2652        arrayReference.receiver.traverse(this, scope);
2653        this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET, this.preferences.insert_space_before_opening_bracket_in_array_reference);
2654        if (this.preferences.insert_space_after_opening_bracket_in_array_reference) {
2655            this.scribe.space();
2656        }
2657        arrayReference.position.traverse(this, scope);
2658        this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET, this.preferences.insert_space_before_closing_bracket_in_array_reference);
2659        
2660        if (numberOfParens > 0) {
2661            manageClosingParenthesizedExpression(arrayReference, numberOfParens);
2662        }
2663        return false;
2664    }
2665    
2666    /**
2667     * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.ArrayTypeReference, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
2668     */

2669    public boolean visit(
2670        ArrayTypeReference arrayTypeReference,
2671        BlockScope scope) {
2672
2673        final int numberOfParens = (arrayTypeReference.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
2674        if (numberOfParens > 0) {
2675            manageOpeningParenthesizedExpression(arrayTypeReference, numberOfParens);
2676        }
2677        this.scribe.printNextToken(SINGLETYPEREFERENCE_EXPECTEDTOKENS);
2678        
2679        int dimensions = getDimensions();
2680        if (dimensions != 0) {
2681            if (this.preferences.insert_space_before_opening_bracket_in_array_type_reference) {
2682                this.scribe.space();
2683            }
2684            for (int i = 0; i < dimensions; i++) {
2685                this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET);
2686                if (this.preferences.insert_space_between_brackets_in_array_type_reference) {
2687                    this.scribe.space();
2688                }
2689                this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET);
2690            }
2691        }
2692        if (numberOfParens > 0) {
2693            manageClosingParenthesizedExpression(arrayTypeReference, numberOfParens);
2694        }
2695        return false;
2696    }
2697
2698    /**
2699     * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.ArrayTypeReference, org.eclipse.jdt.internal.compiler.lookup.ClassScope)
2700     */

2701    public boolean visit(
2702        ArrayTypeReference arrayTypeReference,
2703        ClassScope scope) {
2704
2705        final int numberOfParens = (arrayTypeReference.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
2706        if (numberOfParens > 0) {
2707            manageOpeningParenthesizedExpression(arrayTypeReference, numberOfParens);
2708        }
2709        this.scribe.printNextToken(SINGLETYPEREFERENCE_EXPECTEDTOKENS);
2710        int dimensions = getDimensions();
2711        if (dimensions != 0) {
2712            if (this.preferences.insert_space_before_opening_bracket_in_array_type_reference) {
2713                this.scribe.space();
2714            }
2715            for (int i = 0; i < dimensions; i++) {
2716                this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET);
2717                if (this.preferences.insert_space_between_brackets_in_array_type_reference) {
2718                    this.scribe.space();
2719                }
2720                this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET);
2721            }
2722        }
2723        if (numberOfParens > 0) {
2724            manageClosingParenthesizedExpression(arrayTypeReference, numberOfParens);
2725        }
2726        return false;
2727    }
2728
2729    /**
2730     * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.AssertStatement, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
2731     */

2732    public boolean visit(AssertStatement assertStatement, BlockScope scope) {
2733        
2734        this.scribe.printNextToken(TerminalTokens.TokenNameassert);
2735        this.scribe.space();
2736        assertStatement.assertExpression.traverse(this, scope);
2737        
2738        if (assertStatement.exceptionArgument != null) {
2739            this.scribe.printNextToken(TerminalTokens.TokenNameCOLON, this.preferences.insert_space_before_colon_in_assert);
2740            if (this.preferences.insert_space_after_colon_in_assert) {
2741                this.scribe.space();
2742            }
2743            assertStatement.exceptionArgument.traverse(this, scope);
2744        }
2745        this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
2746        this.scribe.printTrailingComment();
2747        return false;
2748    }
2749    
2750    /**
2751     * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.Assignment, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
2752     */

2753    public boolean visit(Assignment assignment, BlockScope scope) {
2754
2755        final int numberOfParens = (assignment.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
2756        if (numberOfParens > 0) {
2757            manageOpeningParenthesizedExpression(assignment, numberOfParens);
2758        }
2759        assignment.lhs.traverse(this, scope);
2760        this.scribe.printNextToken(TerminalTokens.TokenNameEQUAL, this.preferences.insert_space_before_assignment_operator);
2761        if (this.preferences.insert_space_after_assignment_operator) {
2762            this.scribe.space();
2763        }
2764
2765        Alignment assignmentAlignment = this.scribe.createAlignment("assignmentAlignment", this.preferences.alignment_for_assignment, Alignment.R_OUTERMOST, 1, this.scribe.scanner.currentPosition); //$NON-NLS-1$
2766
this.scribe.enterAlignment(assignmentAlignment);
2767        boolean ok = false;
2768        do {
2769            try {
2770                this.scribe.alignFragment(assignmentAlignment, 0);
2771                assignment.expression.traverse(this, scope);
2772                ok = true;
2773            } catch(AlignmentException e){
2774                this.scribe.redoAlignment(e);
2775            }
2776        } while (!ok);
2777        this.scribe.exitAlignment(assignmentAlignment, true);
2778
2779        if (numberOfParens > 0) {
2780            manageClosingParenthesizedExpression(assignment, numberOfParens);
2781        }
2782        return false;
2783    }
2784
2785    /**
2786     * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.BinaryExpression, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
2787     */

2788    public boolean visit(BinaryExpression binaryExpression, BlockScope scope) {
2789
2790        switch((binaryExpression.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT) {
2791            case OperatorIds.AND :
2792                return dumpBinaryExpression(binaryExpression, TerminalTokens.TokenNameAND, scope);
2793            case OperatorIds.DIVIDE :
2794                return dumpBinaryExpression(binaryExpression, TerminalTokens.TokenNameDIVIDE, scope);
2795            case OperatorIds.GREATER :
2796                return dumpBinaryExpression(binaryExpression, TerminalTokens.TokenNameGREATER, scope);
2797            case OperatorIds.GREATER_EQUAL :
2798                return dumpBinaryExpression(binaryExpression, TerminalTokens.TokenNameGREATER_EQUAL, scope);
2799            case OperatorIds.LEFT_SHIFT :
2800                return dumpBinaryExpression(binaryExpression, TerminalTokens.TokenNameLEFT_SHIFT, scope);
2801            case OperatorIds.LESS :
2802                return dumpBinaryExpression(binaryExpression, TerminalTokens.TokenNameLESS, scope);
2803            case OperatorIds.LESS_EQUAL :
2804                return dumpBinaryExpression(binaryExpression, TerminalTokens.TokenNameLESS_EQUAL, scope);
2805            case OperatorIds.MINUS :
2806                return dumpBinaryExpression(binaryExpression, TerminalTokens.TokenNameMINUS, scope);
2807            case OperatorIds.MULTIPLY :
2808                return dumpBinaryExpression(binaryExpression, TerminalTokens.TokenNameMULTIPLY, scope);
2809            case OperatorIds.OR :
2810                return dumpBinaryExpression(binaryExpression, TerminalTokens.TokenNameOR, scope);
2811            case OperatorIds.PLUS :
2812                return dumpBinaryExpression(binaryExpression, TerminalTokens.TokenNamePLUS, scope);
2813            case OperatorIds.REMAINDER :
2814                return dumpBinaryExpression(binaryExpression, TerminalTokens.TokenNameREMAINDER, scope);
2815            case OperatorIds.RIGHT_SHIFT :
2816                return dumpBinaryExpression(binaryExpression, TerminalTokens.TokenNameRIGHT_SHIFT, scope);
2817            case OperatorIds.UNSIGNED_RIGHT_SHIFT :
2818                return dumpBinaryExpression(binaryExpression, TerminalTokens.TokenNameUNSIGNED_RIGHT_SHIFT, scope);
2819            case OperatorIds.XOR :
2820                return dumpBinaryExpression(binaryExpression, TerminalTokens.TokenNameXOR, scope);
2821            default:
2822                throw new IllegalStateException JavaDoc();
2823        }
2824    }
2825    
2826    /**
2827     * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.Block, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
2828     */

2829    public boolean visit(Block block, BlockScope scope) {
2830        formatBlock(block, scope, this.preferences.brace_position_for_block, this.preferences.insert_space_before_opening_brace_in_block);
2831        return false;
2832    }
2833
2834    /**
2835     * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.BreakStatement, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
2836     */

2837    public boolean visit(BreakStatement breakStatement, BlockScope scope) {
2838        
2839        this.scribe.printNextToken(TerminalTokens.TokenNamebreak);
2840        if (breakStatement.label != null) {
2841            this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, true);
2842        }
2843        this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
2844        this.scribe.printTrailingComment();
2845        return false;
2846    }
2847
2848    /**
2849     * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.CaseStatement, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
2850     */

2851    public boolean visit(CaseStatement caseStatement, BlockScope scope) {
2852        if (caseStatement.constantExpression == null) {
2853            this.scribe.printNextToken(TerminalTokens.TokenNamedefault);
2854            this.scribe.printNextToken(TerminalTokens.TokenNameCOLON, this.preferences.insert_space_before_colon_in_default);
2855        } else {
2856            this.scribe.printNextToken(TerminalTokens.TokenNamecase);
2857            this.scribe.space();
2858            caseStatement.constantExpression.traverse(this, scope);
2859            this.scribe.printNextToken(TerminalTokens.TokenNameCOLON, this.preferences.insert_space_before_colon_in_case);
2860        }
2861        return false;
2862    }
2863
2864
2865
2866    /**
2867     * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.CastExpression, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
2868     */

2869    public boolean visit(CastExpression castExpression, BlockScope scope) {
2870
2871        final int numberOfParens = (castExpression.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
2872        if (numberOfParens > 0) {
2873            manageOpeningParenthesizedExpression(castExpression, numberOfParens);
2874        }
2875        this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN);
2876        if (this.preferences.insert_space_after_opening_paren_in_cast) {
2877            this.scribe.space();
2878        }
2879        castExpression.type.traverse(this, scope);
2880
2881        this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_cast);
2882        if (this.preferences.insert_space_after_closing_paren_in_cast) {
2883            this.scribe.space();
2884        }
2885        castExpression.expression.traverse(this, scope);
2886        
2887        if (numberOfParens > 0) {
2888            manageClosingParenthesizedExpression(castExpression, numberOfParens);
2889        }
2890        return false;
2891    }
2892
2893    /**
2894     * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.CharLiteral, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
2895     */

2896    public boolean visit(CharLiteral charLiteral, BlockScope scope) {
2897
2898        final int numberOfParens = (charLiteral.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
2899        if (numberOfParens > 0) {
2900            manageOpeningParenthesizedExpression(charLiteral, numberOfParens);
2901        }
2902        this.scribe.printNextToken(TerminalTokens.TokenNameCharacterLiteral);
2903
2904        if (numberOfParens > 0) {
2905            manageClosingParenthesizedExpression(charLiteral, numberOfParens);
2906        }
2907        return false;
2908    }
2909
2910
2911    /**
2912     * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.ClassLiteralAccess, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
2913     */

2914    public boolean visit(ClassLiteralAccess classLiteral, BlockScope scope) {
2915
2916        final int numberOfParens = (classLiteral.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
2917        if (numberOfParens > 0) {
2918            manageOpeningParenthesizedExpression(classLiteral, numberOfParens);
2919        }
2920        classLiteral.type.traverse(this, scope);
2921        this.scribe.printNextToken(TerminalTokens.TokenNameDOT);
2922        this.scribe.printNextToken(TerminalTokens.TokenNameclass);
2923        
2924        if (numberOfParens > 0) {
2925            manageClosingParenthesizedExpression(classLiteral, numberOfParens);
2926        }
2927        return false;
2928    }
2929
2930    /**
2931     * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.Clinit, org.eclipse.jdt.internal.compiler.lookup.ClassScope)
2932     */

2933    public boolean visit(Clinit clinit, ClassScope scope) {
2934
2935        return false;
2936    }
2937    
2938    /**
2939     * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration, org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope)
2940     */

2941    public boolean visit(
2942        CompilationUnitDeclaration compilationUnitDeclaration,
2943        CompilationUnitScope scope) {
2944        
2945        // fake new line to handle empty lines before package declaration or import declarations
2946
this.scribe.lastNumberOfNewLines = 1;
2947        /*
2948         * Package declaration
2949         */

2950        final boolean hasPackage = compilationUnitDeclaration.currentPackage != null;
2951        if (hasPackage) {
2952            if (hasComments()) {
2953                this.scribe.printComment();
2954            }
2955            int blankLinesBeforePackage = this.preferences.blank_lines_before_package;
2956            if (blankLinesBeforePackage > 0) {
2957                this.scribe.printEmptyLines(blankLinesBeforePackage);
2958            }
2959
2960            this.scribe.printModifiers(compilationUnitDeclaration.currentPackage.annotations, this);
2961            this.scribe.space();
2962            // dump the package keyword
2963
this.scribe.printNextToken(TerminalTokens.TokenNamepackage);
2964            this.scribe.space();
2965            this.scribe.printQualifiedReference(compilationUnitDeclaration.currentPackage.sourceEnd);
2966            this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
2967            this.scribe.printTrailingComment();
2968            int blankLinesAfterPackage = this.preferences.blank_lines_after_package;
2969            if (blankLinesAfterPackage > 0) {
2970                this.scribe.printEmptyLines(blankLinesAfterPackage);
2971            } else {
2972                this.scribe.printNewLine();
2973            }
2974        } else {
2975            this.scribe.printComment();
2976        }
2977        
2978        /*
2979         * Import statements
2980         */

2981        final ImportReference[] imports = compilationUnitDeclaration.imports;
2982        if (imports != null) {
2983            if (hasPackage) {
2984                int blankLinesBeforeImports = this.preferences.blank_lines_before_imports;
2985                if (blankLinesBeforeImports > 0) {
2986                    this.scribe.printEmptyLines(blankLinesBeforeImports);
2987                }
2988            }
2989            int importLength = imports.length;
2990            int savedNumberOfLineToPreserve = this.preferences.number_of_empty_lines_to_preserve;
2991            if (importLength != 1) {
2992                format(imports[0], false);
2993                for (int i = 1; i < importLength - 1; i++) {
2994                    format(imports[i], false);
2995                }
2996                format(imports[importLength - 1], true);
2997                this.preferences.number_of_empty_lines_to_preserve = savedNumberOfLineToPreserve;
2998            } else {
2999                format(imports[0], true);
3000            }
3001            this.preferences.number_of_empty_lines_to_preserve = savedNumberOfLineToPreserve;
3002            
3003            int blankLinesAfterImports = this.preferences.blank_lines_after_imports;
3004            if (blankLinesAfterImports > 0) {
3005                this.scribe.printEmptyLines(blankLinesAfterImports);
3006            }
3007        }
3008
3009        formatEmptyTypeDeclaration(true);
3010        
3011        int blankLineBetweenTypeDeclarations = this.preferences.blank_lines_between_type_declarations;
3012        /*
3013         * Type declarations
3014         */

3015        final TypeDeclaration[] types = compilationUnitDeclaration.types;
3016        if (types != null) {
3017            int typesLength = types.length;
3018            for (int i = 0; i < typesLength - 1; i++) {
3019                types[i].traverse(this, scope);
3020                formatEmptyTypeDeclaration(false);
3021                if (blankLineBetweenTypeDeclarations != 0) {
3022                    this.scribe.printEmptyLines(blankLineBetweenTypeDeclarations);
3023                } else {
3024                    this.scribe.printNewLine();
3025                }
3026            }
3027            types[typesLength - 1].traverse(this, scope);
3028        }
3029        this.scribe.printEndOfCompilationUnit();
3030        return false;
3031    }
3032
3033    /**
3034     * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.CompoundAssignment, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
3035     */

3036    public boolean visit(
3037        CompoundAssignment compoundAssignment,
3038        BlockScope scope) {
3039            
3040        final int numberOfParens = (compoundAssignment.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
3041        if (numberOfParens > 0) {
3042            manageOpeningParenthesizedExpression(compoundAssignment, numberOfParens);
3043        }
3044        compoundAssignment.lhs.traverse(this, scope);
3045        
3046        /*
3047         * Print the operator
3048         */

3049        int operator;
3050        switch(compoundAssignment.operator) {
3051            case OperatorIds.PLUS :
3052                operator = TerminalTokens.TokenNamePLUS_EQUAL;
3053                break;
3054            case OperatorIds.MINUS :
3055                operator = TerminalTokens.TokenNameMINUS_EQUAL;
3056                break;
3057            case OperatorIds.MULTIPLY :
3058                operator = TerminalTokens.TokenNameMULTIPLY_EQUAL;
3059                break;
3060            case OperatorIds.DIVIDE :
3061                operator = TerminalTokens.TokenNameDIVIDE_EQUAL;
3062                break;
3063            case OperatorIds.AND :
3064                operator = TerminalTokens.TokenNameAND_EQUAL;
3065                break;
3066            case OperatorIds.OR :
3067                operator = TerminalTokens.TokenNameOR_EQUAL;
3068                break;
3069            case OperatorIds.XOR :
3070                operator = TerminalTokens.TokenNameXOR_EQUAL;
3071                break;
3072            case OperatorIds.REMAINDER :
3073                operator = TerminalTokens.TokenNameREMAINDER_EQUAL;
3074                break;
3075            case OperatorIds.LEFT_SHIFT :
3076                operator = TerminalTokens.TokenNameLEFT_SHIFT_EQUAL;
3077                break;
3078            case OperatorIds.RIGHT_SHIFT :
3079                operator = TerminalTokens.TokenNameRIGHT_SHIFT_EQUAL;
3080                break;
3081            default: // OperatorIds.UNSIGNED_RIGHT_SHIFT :
3082
operator = TerminalTokens.TokenNameUNSIGNED_RIGHT_SHIFT_EQUAL;
3083        }
3084        
3085        this.scribe.printNextToken(operator, this.preferences.insert_space_before_assignment_operator);
3086        if (this.preferences.insert_space_after_assignment_operator) {
3087            this.scribe.space();
3088        }
3089        Alignment assignmentAlignment = this.scribe.createAlignment("compoundAssignmentAlignment", this.preferences.alignment_for_assignment, Alignment.R_OUTERMOST, 1, this.scribe.scanner.currentPosition); //$NON-NLS-1$
3090
this.scribe.enterAlignment(assignmentAlignment);
3091        boolean ok = false;
3092        do {
3093            try {
3094                this.scribe.alignFragment(assignmentAlignment, 0);
3095                compoundAssignment.expression.traverse(this, scope);
3096                ok = true;
3097            } catch(AlignmentException e){
3098                this.scribe.redoAlignment(e);
3099            }
3100        } while (!ok);
3101        this.scribe.exitAlignment(assignmentAlignment, true);
3102        
3103        if (numberOfParens > 0) {
3104            manageClosingParenthesizedExpression(compoundAssignment, numberOfParens);
3105        }
3106        return false;
3107    }
3108
3109    /**
3110     * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.ConditionalExpression, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
3111     */

3112    public boolean visit(
3113        ConditionalExpression conditionalExpression,
3114        BlockScope scope) {
3115    
3116        final int numberOfParens = (conditionalExpression.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
3117        if (numberOfParens > 0) {
3118            manageOpeningParenthesizedExpression(conditionalExpression, numberOfParens);
3119        }
3120        conditionalExpression.condition.traverse(this, scope);
3121    
3122        Alignment conditionalExpressionAlignment =this.scribe.createAlignment(
3123                "conditionalExpression", //$NON-NLS-1$
3124
this.preferences.alignment_for_conditional_expression,
3125                2,
3126                this.scribe.scanner.currentPosition);
3127    
3128        this.scribe.enterAlignment(conditionalExpressionAlignment);
3129        boolean ok = false;
3130        do {
3131            try {
3132                this.scribe.alignFragment(conditionalExpressionAlignment, 0);
3133                this.scribe.printNextToken(TerminalTokens.TokenNameQUESTION, this.preferences.insert_space_before_question_in_conditional);
3134    
3135                if (this.preferences.insert_space_after_question_in_conditional) {
3136                    this.scribe.space();
3137                }
3138                conditionalExpression.valueIfTrue.traverse(this, scope);
3139                this.scribe.printTrailingComment();
3140                this.scribe.alignFragment(conditionalExpressionAlignment, 1);
3141                this.scribe.printNextToken(TerminalTokens.TokenNameCOLON, this.preferences.insert_space_before_colon_in_conditional);
3142    
3143                if (this.preferences.insert_space_after_colon_in_conditional) {
3144                    this.scribe.space();
3145                }
3146                conditionalExpression.valueIfFalse.traverse(this, scope);
3147    
3148                ok = true;
3149            } catch (AlignmentException e) {
3150                this.scribe.redoAlignment(e);
3151            }
3152        } while (!ok);
3153        this.scribe.exitAlignment(conditionalExpressionAlignment, true);
3154            
3155        if (numberOfParens > 0) {
3156            manageClosingParenthesizedExpression(conditionalExpression, numberOfParens);
3157        }
3158        return false;
3159    }
3160
3161
3162    /**
3163     * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration, org.eclipse.jdt.internal.compiler.lookup.ClassScope)
3164     */

3165    public boolean visit(
3166        ConstructorDeclaration constructorDeclaration,
3167        ClassScope scope) {
3168            
3169        if (constructorDeclaration.ignoreFurtherInvestigation) {
3170            this.scribe.printComment();
3171            if (this.scribe.indentationLevel != 0) {
3172                this.scribe.printIndentationIfNecessary();
3173            }
3174            this.scribe.scanner.resetTo(constructorDeclaration.declarationSourceEnd + 1, this.scribe.scannerEndPosition - 1);
3175            this.scribe.printTrailingComment();
3176            switch(this.scribe.scanner.source[this.scribe.scanner.currentPosition]) {
3177                case '\n' :
3178                    this.scribe.scanner.currentPosition++;
3179                    this.scribe.lastNumberOfNewLines = 1;
3180                    break;
3181                case '\r' :
3182                    this.scribe.scanner.currentPosition++;
3183                    if (this.scribe.scanner.source[this.scribe.scanner.currentPosition] == '\n') {
3184                        this.scribe.scanner.currentPosition++;
3185                    }
3186                    this.scribe.lastNumberOfNewLines = 1;
3187            }
3188            return false;
3189        }
3190        /*
3191         * Print comments to get proper line number
3192         */

3193        this.scribe.printComment();
3194        int line = this.scribe.line;
3195        this.scribe.printModifiers(constructorDeclaration.annotations, this);
3196        if (this.scribe.line > line) {
3197            // annotations introduced new line, but this is not a line wrapping
3198
// see 158267
3199
line = this.scribe.line;
3200        }
3201        this.scribe.space();
3202
3203        TypeParameter[] typeParameters = constructorDeclaration.typeParameters;
3204        if (typeParameters != null) {
3205            this.scribe.printNextToken(TerminalTokens.TokenNameLESS, this.preferences.insert_space_before_opening_angle_bracket_in_type_parameters);
3206            if (this.preferences.insert_space_after_opening_angle_bracket_in_type_parameters) {
3207                this.scribe.space();
3208            }
3209            int length = typeParameters.length;
3210            for (int i = 0; i < length - 1; i++) {
3211                typeParameters[i].traverse(this, constructorDeclaration.scope);
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            typeParameters[length - 1].traverse(this, constructorDeclaration.scope);
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        /*
3227         * Print the method name
3228         */

3229        this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, true);
3230
3231        formatMethodArguments(
3232            constructorDeclaration,
3233            this.preferences.insert_space_before_opening_paren_in_constructor_declaration,
3234            this.preferences.insert_space_between_empty_parens_in_constructor_declaration,
3235            this.preferences.insert_space_before_closing_paren_in_constructor_declaration,
3236            this.preferences.insert_space_after_opening_paren_in_constructor_declaration,
3237            this.preferences.insert_space_before_comma_in_constructor_declaration_parameters,
3238            this.preferences.insert_space_after_comma_in_constructor_declaration_parameters,
3239            this.preferences.alignment_for_parameters_in_constructor_declaration);
3240
3241        formatThrowsClause(
3242                constructorDeclaration,
3243                this.preferences.insert_space_before_comma_in_constructor_declaration_throws,
3244                this.preferences.insert_space_after_comma_in_constructor_declaration_throws,
3245                this.preferences.alignment_for_throws_clause_in_constructor_declaration);
3246
3247        if (!constructorDeclaration.isNative() && !constructorDeclaration.isAbstract()) {
3248            /*
3249             * Method body
3250             */

3251            String JavaDoc constructor_declaration_brace = this.preferences.brace_position_for_constructor_declaration;
3252            formatLeftCurlyBrace(line, constructor_declaration_brace);
3253            formatOpeningBrace(constructor_declaration_brace, this.preferences.insert_space_before_opening_brace_in_constructor_declaration);
3254            final int numberOfBlankLinesAtBeginningOfMethodBody = this.preferences.blank_lines_at_beginning_of_method_body;
3255            if (numberOfBlankLinesAtBeginningOfMethodBody > 0) {
3256                this.scribe.printEmptyLines(numberOfBlankLinesAtBeginningOfMethodBody);
3257            }
3258            if (constructorDeclaration.constructorCall != null && !constructorDeclaration.constructorCall.isImplicitSuper()) {
3259                this.scribe.printNewLine();
3260                if (this.preferences.indent_statements_compare_to_body) {
3261                    this.scribe.indent();
3262                }
3263                constructorDeclaration.constructorCall.traverse(this, constructorDeclaration.scope);
3264                if (this.preferences.indent_statements_compare_to_body) {
3265                    this.scribe.unIndent();
3266                }
3267            }
3268            final Statement[] statements = constructorDeclaration.statements;
3269            if (statements != null) {
3270                this.scribe.printNewLine();
3271                if (this.preferences.indent_statements_compare_to_body) {
3272                    this.scribe.indent();
3273                }
3274                formatStatements(constructorDeclaration.scope, statements, true);
3275                this.scribe.printComment();
3276                if (this.preferences.indent_statements_compare_to_body) {
3277                    this.scribe.unIndent();
3278                }
3279            } else if (this.preferences.insert_new_line_in_empty_method_body) {
3280                this.scribe.printNewLine();
3281                if (this.preferences.indent_statements_compare_to_body) {
3282                    this.scribe.indent();
3283                }
3284                this.scribe.printComment();
3285                if (this.preferences.indent_statements_compare_to_body) {
3286                    this.scribe.unIndent();
3287                }
3288            }
3289            this.scribe.printNextToken(TerminalTokens.TokenNameRBRACE);
3290            this.scribe.printTrailingComment();
3291            if (constructor_declaration_brace.equals(DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED)) {
3292                this.scribe.unIndent();
3293            }
3294        } else {
3295            // no method body
3296
this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
3297            this.scribe.printTrailingComment();
3298        }
3299        return false;
3300    }
3301
3302    /**
3303     * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.ContinueStatement, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
3304     */

3305    public boolean visit(ContinueStatement continueStatement, BlockScope scope) {
3306
3307        this.scribe.printNextToken(TerminalTokens.TokenNamecontinue);
3308        if (continueStatement.label != null) {
3309            this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, true);
3310        }
3311        this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
3312        this.scribe.printTrailingComment();
3313        return false;
3314    }
3315
3316
3317    /**
3318     * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.DoStatement, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
3319     */

3320    public boolean visit(DoStatement doStatement, BlockScope scope) {
3321
3322        this.scribe.printNextToken(TerminalTokens.TokenNamedo);
3323        final int line = this.scribe.line;
3324        
3325        final Statement action = doStatement.action;
3326        if (action != null) {
3327            if (action instanceof Block) {
3328                formatLeftCurlyBrace(line, this.preferences.brace_position_for_block);
3329                action.traverse(this, scope);
3330            } else if (action instanceof EmptyStatement) {
3331                /*
3332                 * This is an empty statement
3333                 */

3334                formatNecessaryEmptyStatement();
3335            } else {
3336                this.scribe.printNewLine();
3337                this.scribe.indent();
3338                action.traverse(this, scope);
3339                if (action instanceof Expression) {
3340                    this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
3341                    this.scribe.printTrailingComment();
3342                }
3343                this.scribe.printNewLine();
3344                this.scribe.unIndent();
3345            }
3346        } else {
3347            /*
3348             * This is an empty statement
3349             */

3350            formatNecessaryEmptyStatement();
3351        }
3352        
3353        if (this.preferences.insert_new_line_before_while_in_do_statement) {
3354            this.scribe.printNewLine();
3355        }
3356        this.scribe.printNextToken(TerminalTokens.TokenNamewhile, this.preferences.insert_space_after_closing_brace_in_block);
3357        this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_while);
3358        
3359        if (this.preferences.insert_space_after_opening_paren_in_while) {
3360            this.scribe.space();
3361        }
3362        
3363        doStatement.condition.traverse(this, scope);
3364        
3365        this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_while);
3366        this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
3367        this.scribe.printTrailingComment();
3368        return false;
3369    }
3370
3371    /**
3372     * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.DoubleLiteral, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
3373     */

3374    public boolean visit(DoubleLiteral doubleLiteral, BlockScope scope) {
3375
3376        final int numberOfParens = (doubleLiteral.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
3377        if (numberOfParens > 0) {
3378            manageOpeningParenthesizedExpression(doubleLiteral, numberOfParens);
3379        }
3380        Constant constant = doubleLiteral.constant;
3381        if (constant != null && constant.doubleValue() < 0) {
3382            this.scribe.printNextToken(TerminalTokens.TokenNameMINUS);
3383        }
3384        this.scribe.printNextToken(TerminalTokens.TokenNameDoubleLiteral);
3385
3386        if (numberOfParens > 0) {
3387            manageClosingParenthesizedExpression(doubleLiteral, numberOfParens);
3388        }
3389        return false;
3390    }
3391
3392    /**
3393     * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.EmptyStatement, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
3394     */

3395    public boolean visit(EmptyStatement statement, BlockScope scope) {
3396        if (this.preferences.put_empty_statement_on_new_line) {
3397            this.scribe.printNewLine();
3398        }
3399        this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
3400        this.scribe.printTrailingComment();
3401        return false;
3402    }
3403    // field is an enum constant
3404
public boolean visit(FieldDeclaration enumConstant, MethodScope scope) {
3405        /*
3406         * Print comments to get proper line number
3407         */

3408        this.scribe.printComment();
3409        final int line = this.scribe.line;
3410        
3411        this.scribe.printModifiers(enumConstant.annotations, this);
3412        this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, false);
3413        formatEnumConstantArguments(
3414            enumConstant,
3415            this.preferences.insert_space_before_opening_paren_in_enum_constant,
3416            this.preferences.insert_space_between_empty_parens_in_enum_constant,
3417            this.preferences.insert_space_before_closing_paren_in_enum_constant,
3418            this.preferences.insert_space_after_opening_paren_in_enum_constant,
3419            this.preferences.insert_space_before_comma_in_enum_constant_arguments,
3420            this.preferences.insert_space_after_comma_in_enum_constant_arguments,
3421            this.preferences.alignment_for_arguments_in_enum_constant);
3422        
3423        Expression initialization = enumConstant.initialization;
3424        if (initialization instanceof QualifiedAllocationExpression) {
3425            TypeDeclaration typeDeclaration = ((QualifiedAllocationExpression) initialization).anonymousType;
3426            int fieldsCount = typeDeclaration.fields == null ? 0 : typeDeclaration.fields.length;
3427            int methodsCount = typeDeclaration.methods == null ? 0 : typeDeclaration.methods.length;
3428            int membersCount = typeDeclaration.memberTypes == null ? 0 : typeDeclaration.memberTypes.length;
3429            
3430            /*
3431             * Type body
3432             */

3433            String JavaDoc enum_constant_brace = this.preferences.brace_position_for_enum_constant;
3434    
3435            formatLeftCurlyBrace(line, enum_constant_brace);
3436            formatTypeOpeningBraceForEnumConstant(enum_constant_brace, this.preferences.insert_space_before_opening_brace_in_enum_constant, typeDeclaration);
3437            
3438            if (this.preferences.indent_body_declarations_compare_to_enum_constant_header) {
3439                this.scribe.indent();
3440            }
3441    
3442            if (fieldsCount != 0 || methodsCount != 0 || membersCount != 0) {
3443                formatTypeMembers(typeDeclaration);
3444            }
3445
3446            if (this.preferences.indent_body_declarations_compare_to_enum_constant_header) {
3447                this.scribe.unIndent();
3448            }
3449            
3450            if (this.preferences.insert_new_line_in_empty_enum_constant) {
3451                this.scribe.printNewLine();
3452            }
3453            this.scribe.printNextToken(TerminalTokens.TokenNameRBRACE);
3454            this.scribe.printTrailingComment();
3455            if (enum_constant_brace.equals(DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED)) {
3456                this.scribe.unIndent();
3457            }
3458            if (hasComments()) {
3459                this.scribe.printNewLine();
3460            }
3461        }
3462        return false;
3463    }
3464    /**
3465     * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.EqualExpression, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
3466     */

3467    public boolean visit(EqualExpression equalExpression, BlockScope scope) {
3468
3469        if ((equalExpression.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT == OperatorIds.EQUAL_EQUAL) {
3470            return dumpEqualityExpression(equalExpression, TerminalTokens.TokenNameEQUAL_EQUAL, scope);
3471        } else {
3472            return dumpEqualityExpression(equalExpression, TerminalTokens.TokenNameNOT_EQUAL, scope);
3473        }
3474    }
3475
3476    /**
3477     * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
3478     */

3479    public boolean visit(
3480        ExplicitConstructorCall explicitConstructor,
3481        BlockScope scope) {
3482
3483        if (explicitConstructor.isImplicitSuper()) {
3484            return false;
3485        }
3486        final Expression qualification = explicitConstructor.qualification;
3487        if (qualification != null) {
3488            qualification.traverse(this, scope);
3489            this.scribe.printNextToken(TerminalTokens.TokenNameDOT);
3490        }
3491
3492        TypeReference[] typeArguments = explicitConstructor.typeArguments;
3493        if (typeArguments != null) {
3494                this.scribe.printNextToken(TerminalTokens.TokenNameLESS, this.preferences.insert_space_before_opening_angle_bracket_in_type_arguments);
3495                if (this.preferences.insert_space_after_opening_angle_bracket_in_type_arguments) {
3496                    this.scribe.space();
3497                }
3498                int length = typeArguments.length;
3499                for (int i = 0; i < length - 1; i++) {
3500                    typeArguments[i].traverse(this, scope);
3501                    this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_type_arguments);
3502                    if (this.preferences.insert_space_after_comma_in_type_arguments) {
3503                        this.scribe.space();
3504                    }
3505                }
3506                typeArguments[length - 1].traverse(this, scope);
3507                if (isClosingGenericToken()) {
3508                    this.scribe.printNextToken(CLOSING_GENERICS_EXPECTEDTOKENS, this.preferences.insert_space_before_closing_angle_bracket_in_type_arguments);
3509                }
3510                if (this.preferences.insert_space_after_closing_angle_bracket_in_type_arguments) {
3511                    this.scribe.space();
3512                }
3513        }
3514        
3515        if (explicitConstructor.isSuperAccess()) {
3516            this.scribe.printNextToken(TerminalTokens.TokenNamesuper);
3517        } else {
3518            this.scribe.printNextToken(TerminalTokens.TokenNamethis);
3519        }
3520        this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_method_invocation);
3521        
3522        final Expression[] arguments = explicitConstructor.arguments;
3523        if (arguments != null) {
3524            if (this.preferences.insert_space_after_opening_paren_in_method_invocation) {
3525                this.scribe.space();
3526            }
3527            int argumentLength = arguments.length;
3528            Alignment argumentsAlignment =this.scribe.createAlignment(
3529                    "explicit_constructor_call",//$NON-NLS-1$
3530
this.preferences.alignment_for_arguments_in_explicit_constructor_call,
3531                    argumentLength,
3532                    this.scribe.scanner.currentPosition);
3533            this.scribe.enterAlignment(argumentsAlignment);
3534            boolean ok = false;
3535            do {
3536                try {
3537                    for (int i = 0; i < argumentLength; i++) {
3538                        if (i > 0) {
3539                            this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_explicit_constructor_call_arguments);
3540                            this.scribe.printTrailingComment();
3541                        }
3542                        this.scribe.alignFragment(argumentsAlignment, i);
3543                        if (i > 0 && this.preferences.insert_space_after_comma_in_explicit_constructor_call_arguments) {
3544                            this.scribe.space();
3545                        }
3546                        arguments[i].traverse(this, scope);
3547                    }
3548                    ok = true;
3549                } catch (AlignmentException e) {
3550                    this.scribe.redoAlignment(e);
3551                }
3552            } while (!ok);
3553            this.scribe.exitAlignment(argumentsAlignment, true);
3554            this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_method_invocation);
3555        } else {
3556            this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_between_empty_parens_in_method_invocation);
3557        }
3558        this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
3559        this.scribe.printTrailingComment();
3560        return false;
3561    }
3562    /**
3563     * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.FalseLiteral, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
3564     */

3565    public boolean visit(FalseLiteral falseLiteral, BlockScope scope) {
3566
3567        final int numberOfParens = (falseLiteral.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
3568        if (numberOfParens > 0) {
3569            manageOpeningParenthesizedExpression(falseLiteral, numberOfParens);
3570        }
3571        this.scribe.printNextToken(TerminalTokens.TokenNamefalse);
3572
3573        if (numberOfParens > 0) {
3574            manageClosingParenthesizedExpression(falseLiteral, numberOfParens);
3575        }
3576        return false;
3577    }
3578    /**
3579     * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.FieldReference, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
3580     */

3581    public boolean visit(FieldReference fieldReference, BlockScope scope) {
3582
3583        final int numberOfParens = (fieldReference.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
3584        if (numberOfParens > 0) {
3585            manageOpeningParenthesizedExpression(fieldReference, numberOfParens);
3586        }
3587        fieldReference.receiver.traverse(this, scope);
3588        this.scribe.printNextToken(TerminalTokens.TokenNameDOT);
3589        this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier);
3590        
3591        if (numberOfParens > 0) {
3592            manageClosingParenthesizedExpression(fieldReference, numberOfParens);
3593        }
3594        return false;
3595    }
3596
3597    /**
3598     * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.FloatLiteral, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
3599     */

3600    public boolean visit(FloatLiteral floatLiteral, BlockScope scope) {
3601
3602        final int numberOfParens = (floatLiteral.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
3603        if (numberOfParens > 0) {
3604            manageOpeningParenthesizedExpression(floatLiteral, numberOfParens);
3605        }
3606        Constant constant = floatLiteral.constant;
3607        if (constant != null && floatLiteral.constant.floatValue() < 0) {
3608            this.scribe.printNextToken(TerminalTokens.TokenNameMINUS);
3609        }
3610        this.scribe.printNextToken(TerminalTokens.TokenNameFloatingPointLiteral);
3611
3612        if (numberOfParens > 0) {
3613            manageClosingParenthesizedExpression(floatLiteral, numberOfParens);
3614        }
3615        return false;
3616    }
3617    public boolean visit(ForeachStatement forStatement, BlockScope scope) {
3618        this.scribe.printNextToken(TerminalTokens.TokenNamefor);
3619        final int line = this.scribe.line;
3620        this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_for);
3621        
3622        if (this.preferences.insert_space_after_opening_paren_in_for) {
3623            this.scribe.space();
3624        }
3625        formatLocalDeclaration(forStatement.elementVariable, scope, false, false);
3626
3627        this.scribe.printNextToken(TerminalTokens.TokenNameCOLON, this.preferences.insert_space_before_colon_in_for);
3628        if (this.preferences.insert_space_after_colon_in_for) {
3629            this.scribe.space();
3630        }
3631        forStatement.collection.traverse(this, scope);
3632
3633        this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_for);
3634        
3635        final Statement action = forStatement.action;
3636        if (action != null) {
3637            if (action instanceof Block) {
3638                formatLeftCurlyBrace(line, this.preferences.brace_position_for_block);
3639                action.traverse(this, scope);
3640            } else if (action instanceof EmptyStatement) {
3641                /*
3642                 * This is an empty statement
3643                 */

3644                formatNecessaryEmptyStatement();
3645            } else {
3646                this.scribe.indent();
3647                this.scribe.printNewLine();
3648                action.traverse(this, scope);
3649                this.scribe.unIndent();
3650            }
3651            if (action instanceof Expression) {
3652                this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
3653                this.scribe.printTrailingComment();
3654            }
3655        } else {
3656            /*
3657             * This is an empty statement
3658             */

3659            formatNecessaryEmptyStatement();
3660        }
3661        return false;
3662    }
3663
3664    /**
3665     * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.ForStatement, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
3666     */

3667    public boolean visit(ForStatement forStatement, BlockScope scope) {
3668    
3669        this.scribe.printNextToken(TerminalTokens.TokenNamefor);
3670        final int line = this.scribe.line;
3671        this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_for);
3672        
3673        if (this.preferences.insert_space_after_opening_paren_in_for) {
3674            this.scribe.space();
3675        }
3676        final Statement[] initializations = forStatement.initializations;
3677        if (initializations != null) {
3678            int length = initializations.length;
3679            for (int i = 0; i < length; i++) {
3680                if (initializations[i] instanceof LocalDeclaration) {
3681                    formatLocalDeclaration((LocalDeclaration) initializations[i], scope, this.preferences.insert_space_before_comma_in_for_inits, this.preferences.insert_space_after_comma_in_for_inits);
3682                } else {
3683                    initializations[i].traverse(this, scope);
3684                    if (i >= 0 && (i < length - 1)) {
3685                        this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_for_inits);
3686                        if (this.preferences.insert_space_after_comma_in_for_inits) {
3687                            this.scribe.space();
3688                        }
3689                        this.scribe.printTrailingComment();
3690                    }
3691                }
3692            }
3693        }
3694        this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon_in_for);
3695        final Expression condition = forStatement.condition;
3696        if (condition != null) {
3697            if (this.preferences.insert_space_after_semicolon_in_for) {
3698                this.scribe.space();
3699            }
3700            condition.traverse(this, scope);
3701        }
3702        this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon_in_for);
3703        final Statement[] increments = forStatement.increments;
3704        if (increments != null) {
3705            if (this.preferences.insert_space_after_semicolon_in_for) {
3706                this.scribe.space();
3707            }
3708            for (int i = 0, length = increments.length; i < length; i++) {
3709                increments[i].traverse(this, scope);
3710                if (i != length - 1) {
3711                    this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_for_increments);
3712                    if (this.preferences.insert_space_after_comma_in_for_increments) {
3713                        this.scribe.space();
3714                    }
3715                    this.scribe.printTrailingComment();
3716                }
3717            }
3718        }
3719        this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_for);
3720        
3721        final Statement action = forStatement.action;
3722        if (action != null) {
3723            if (action instanceof Block) {
3724                formatLeftCurlyBrace(line, this.preferences.brace_position_for_block);
3725                action.traverse(this, scope);
3726            } else if (action instanceof EmptyStatement) {
3727                /*
3728                 * This is an empty statement
3729                 */

3730                formatNecessaryEmptyStatement();
3731            } else {
3732                this.scribe.indent();
3733                this.scribe.printNewLine();
3734                action.traverse(this, scope);
3735                this.scribe.unIndent();
3736            }
3737            if (action instanceof Expression) {
3738                this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
3739                this.scribe.printTrailingComment();
3740            }
3741        } else {
3742            /*
3743             * This is an empty statement
3744             */

3745            formatNecessaryEmptyStatement();
3746        }
3747        return false;
3748    }
3749
3750
3751    /**
3752     * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.IfStatement, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
3753     */

3754    public boolean visit(IfStatement ifStatement, BlockScope scope) {
3755
3756        this.scribe.printNextToken(TerminalTokens.TokenNameif);
3757        final int line = this.scribe.line;
3758        this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_if);
3759        if (this.preferences.insert_space_after_opening_paren_in_if) {
3760            this.scribe.space();
3761        }
3762        ifStatement.condition.traverse(this, scope);
3763        this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_if);
3764
3765        final Statement thenStatement = ifStatement.thenStatement;
3766        final Statement elseStatement = ifStatement.elseStatement;
3767
3768        boolean thenStatementIsBlock = false;
3769        if (thenStatement != null) {
3770            if (thenStatement instanceof Block) {
3771                thenStatementIsBlock = true;
3772                if (isGuardClause((Block)thenStatement) && elseStatement == null && this.preferences.keep_guardian_clause_on_one_line) {
3773                    /*
3774                     * Need a specific formatting for guard clauses
3775                     * guard clauses are block with a single return or throw
3776                     * statement
3777                     */

3778                     formatGuardClauseBlock((Block) thenStatement, scope);
3779                } else {
3780                    formatLeftCurlyBrace(line, this.preferences.brace_position_for_block);
3781                    thenStatement.traverse(this, scope);
3782                    if (elseStatement != null && (this.preferences.insert_new_line_before_else_in_if_statement)) {
3783                        this.scribe.printNewLine();
3784                    }
3785                }
3786            } else if (elseStatement == null && this.preferences.keep_simple_if_on_one_line) {
3787                Alignment compactIfAlignment = this.scribe.createAlignment(
3788                        "compactIf", //$NON-NLS-1$
3789
this.preferences.alignment_for_compact_if,
3790                        Alignment.R_OUTERMOST,
3791                        1,
3792                        this.scribe.scanner.currentPosition,
3793                        1,
3794                        false);
3795                this.scribe.enterAlignment(compactIfAlignment);
3796                boolean ok = false;
3797                do {
3798                    try {
3799                        this.scribe.alignFragment(compactIfAlignment, 0);
3800                        this.scribe.space();
3801                        thenStatement.traverse(this, scope);
3802                        if (thenStatement instanceof Expression) {
3803                            this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
3804                            this.scribe.printTrailingComment();
3805                        }
3806                        ok = true;
3807                    } catch (AlignmentException e) {
3808                        this.scribe.redoAlignment(e);
3809                    }
3810                } while (!ok);
3811                this.scribe.exitAlignment(compactIfAlignment, true);
3812            } else if (this.preferences.keep_then_statement_on_same_line) {
3813                this.scribe.space();
3814                thenStatement.traverse(this, scope);
3815                if (thenStatement instanceof Expression) {
3816                    this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
3817                    this.scribe.printTrailingComment();
3818                }
3819                if (elseStatement != null) {
3820                    this.scribe.printNewLine();
3821                }
3822            } else {
3823                this.scribe.printTrailingComment();
3824                this.scribe.printNewLine();
3825                this.scribe.indent();
3826                thenStatement.traverse(this, scope);
3827                if (thenStatement instanceof Expression) {
3828                    this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
3829                    this.scribe.printTrailingComment();
3830                }
3831                if (elseStatement != null) {
3832                    this.scribe.printNewLine();
3833                }
3834                this.scribe.unIndent();
3835            }
3836        }
3837        
3838        if (elseStatement != null) {
3839            if (thenStatementIsBlock) {
3840                this.scribe.printNextToken(TerminalTokens.TokenNameelse, this.preferences.insert_space_after_closing_brace_in_block);
3841            } else {
3842                this.scribe.printNextToken(TerminalTokens.TokenNameelse, true);
3843            }
3844            if (elseStatement instanceof Block) {
3845                elseStatement.traverse(this, scope);
3846            } else if (elseStatement instanceof IfStatement) {
3847                if (!this.preferences.compact_else_if) {
3848                    this.scribe.printNewLine();
3849                    this.scribe.indent();
3850                }
3851                this.scribe.space();
3852                elseStatement.traverse(this, scope);
3853                if (!this.preferences.compact_else_if) {
3854                    this.scribe.unIndent();
3855                }
3856            } else if (this.preferences.keep_else_statement_on_same_line) {
3857                this.scribe.space();
3858                elseStatement.traverse(this, scope);
3859                if (elseStatement instanceof Expression) {
3860                    this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
3861                    this.scribe.printTrailingComment();
3862                }
3863            } else {
3864                this.scribe.printNewLine();
3865                this.scribe.indent();
3866                elseStatement.traverse(this, scope);
3867                if (elseStatement instanceof Expression) {
3868                    this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
3869                    this.scribe.printTrailingComment();
3870                }
3871                this.scribe.unIndent();
3872            }
3873        }
3874        return false;
3875    }
3876
3877    /**
3878     * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.Initializer, org.eclipse.jdt.internal.compiler.lookup.MethodScope)
3879     */

3880    public boolean visit(Initializer initializer, MethodScope scope) {
3881
3882        if (initializer.isStatic()) {
3883            this.scribe.printNextToken(TerminalTokens.TokenNamestatic);
3884        }
3885        initializer.block.traverse(this, scope);
3886        return false;
3887    }
3888
3889    /**
3890     * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.InstanceOfExpression, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
3891     */

3892    public boolean visit(
3893        InstanceOfExpression instanceOfExpression,
3894        BlockScope scope) {
3895
3896        final int numberOfParens = (instanceOfExpression.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
3897        if (numberOfParens > 0) {
3898            manageOpeningParenthesizedExpression(instanceOfExpression, numberOfParens);
3899        }
3900        instanceOfExpression.expression.traverse(this, scope);
3901        this.scribe.printNextToken(TerminalTokens.TokenNameinstanceof, true);
3902        this.scribe.space();
3903        instanceOfExpression.type.traverse(this, scope);
3904        
3905        if (numberOfParens > 0) {
3906            manageClosingParenthesizedExpression(instanceOfExpression, numberOfParens);
3907        }
3908        return false;
3909    }
3910
3911    /**
3912     * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.IntLiteral, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
3913     */

3914    public boolean visit(IntLiteral intLiteral, BlockScope scope) {
3915
3916        final int numberOfParens = (intLiteral.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
3917        if (numberOfParens > 0) {
3918            manageOpeningParenthesizedExpression(intLiteral, numberOfParens);
3919        }
3920        Constant constant = intLiteral.constant;
3921        if (constant != null && constant.intValue() < 0) {
3922            this.scribe.printNextToken(TerminalTokens.TokenNameMINUS);
3923        }
3924        this.scribe.printNextToken(TerminalTokens.TokenNameIntegerLiteral);
3925
3926        if (numberOfParens > 0) {
3927            manageClosingParenthesizedExpression(intLiteral, numberOfParens);
3928        }
3929        return false;
3930    }
3931
3932
3933    /**
3934     * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.LabeledStatement, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
3935     */

3936    public boolean visit(LabeledStatement labeledStatement, BlockScope scope) {
3937
3938        this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier);
3939        this.scribe.printNextToken(TerminalTokens.TokenNameCOLON, this.preferences.insert_space_before_colon_in_labeled_statement);
3940        if (this.preferences.insert_space_after_colon_in_labeled_statement) {
3941            this.scribe.space();
3942        }
3943        final Statement statement = labeledStatement.statement;
3944        statement.traverse(this, scope);
3945        if (statement instanceof Expression) {
3946            this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
3947            this.scribe.printTrailingComment();
3948        }
3949        return false;
3950    }
3951
3952    /**
3953     * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.LocalDeclaration, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
3954     */

3955    public boolean visit(LocalDeclaration localDeclaration, BlockScope scope) {
3956        formatLocalDeclaration(localDeclaration, scope, this.preferences.insert_space_before_comma_in_multiple_local_declarations, this.preferences.insert_space_after_comma_in_multiple_local_declarations);
3957        return false;
3958    }
3959
3960    /**
3961     * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.LongLiteral, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
3962     */

3963    public boolean visit(LongLiteral longLiteral, BlockScope scope) {
3964
3965        final int numberOfParens = (longLiteral.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
3966        if (numberOfParens > 0) {
3967            manageOpeningParenthesizedExpression(longLiteral, numberOfParens);
3968        }
3969        Constant constant = longLiteral.constant;
3970        if (constant != null && constant.longValue() < 0) {
3971            this.scribe.printNextToken(TerminalTokens.TokenNameMINUS);
3972        }
3973        this.scribe.printNextToken(TerminalTokens.TokenNameLongLiteral);
3974
3975        if (numberOfParens > 0) {
3976            manageClosingParenthesizedExpression(longLiteral, numberOfParens);
3977        }
3978        return false;
3979    }
3980    public boolean visit(MarkerAnnotation annotation, BlockScope scope) {
3981        this.scribe.printNextToken(TerminalTokens.TokenNameAT);
3982        if (this.preferences.insert_space_after_at_in_annotation) {
3983            this.scribe.space();
3984        }
3985        this.scribe.printQualifiedReference(annotation.sourceEnd);
3986        return false;
3987    }
3988    public boolean visit(MarkerAnnotation annotation, ClassScope scope) {
3989        this.scribe.printNextToken(TerminalTokens.TokenNameAT);
3990        if (this.preferences.insert_space_after_at_in_annotation) {
3991            this.scribe.space();
3992        }
3993        this.scribe.printQualifiedReference(annotation.sourceEnd);
3994        return false;
3995    }
3996    public boolean visit(MemberValuePair pair, BlockScope scope) {
3997        this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier);
3998        this.scribe.printNextToken(TerminalTokens.TokenNameEQUAL, this.preferences.insert_space_before_assignment_operator);
3999        if (this.preferences.insert_space_after_assignment_operator) {
4000            this.scribe.space();
4001        }
4002        pair.value.traverse(this, scope);
4003        return false;
4004    }
4005    /**
4006     * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.MessageSend, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
4007     */

4008    public boolean visit(MessageSend messageSend, BlockScope scope) {
4009
4010        final int numberOfParens = (messageSend.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
4011        if (numberOfParens > 0) {
4012            manageOpeningParenthesizedExpression(messageSend, numberOfParens);
4013        }
4014        CascadingMethodInvocationFragmentBuilder builder = buildFragments(messageSend, scope);
4015        
4016        if (builder.size() >= 3 && numberOfParens == 0) {
4017            formatCascadingMessageSends(builder, scope);
4018        } else {
4019            Alignment messageAlignment = null;
4020            if (!messageSend.receiver.isImplicitThis()) {
4021                messageSend.receiver.traverse(this, scope);
4022                messageAlignment = this.scribe.createAlignment(
4023                        "messageAlignment", //$NON-NLS-1$
4024
this.preferences.alignment_for_selector_in_method_invocation,
4025                        1,
4026                        this.scribe.scanner.currentPosition);
4027                this.scribe.enterAlignment(messageAlignment);
4028                boolean ok = false;
4029                do {
4030                    try {
4031                        formatMessageSend(messageSend, scope, messageAlignment);
4032                        ok = true;
4033                    } catch (AlignmentException e) {
4034                        this.scribe.redoAlignment(e);
4035                    }
4036                } while (!ok);
4037                this.scribe.exitAlignment(messageAlignment, true);
4038            } else {
4039                formatMessageSend(messageSend, scope, null);
4040            }
4041        }
4042        if (numberOfParens > 0) {
4043            manageClosingParenthesizedExpression(messageSend, numberOfParens);
4044        }
4045        return false;
4046    }
4047
4048    /**
4049     * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.MethodDeclaration, org.eclipse.jdt.internal.compiler.lookup.ClassScope)
4050     */

4051    public boolean visit(
4052        MethodDeclaration methodDeclaration,
4053        ClassScope scope) {
4054
4055        if (methodDeclaration.ignoreFurtherInvestigation) {
4056            this.scribe.printComment();
4057            if (this.scribe.indentationLevel != 0) {
4058                this.scribe.printIndentationIfNecessary();
4059            }
4060            this.scribe.scanner.resetTo(methodDeclaration.declarationSourceEnd + 1, this.scribe.scannerEndPosition - 1);
4061            this.scribe.printTrailingComment();
4062            switch(this.scribe.scanner.source[this.scribe.scanner.currentPosition]) {
4063                case '\n' :
4064                    this.scribe.scanner.currentPosition++;
4065                    this.scribe.lastNumberOfNewLines = 1;
4066                    break;
4067                case '\r' :
4068                    this.scribe.scanner.currentPosition++;
4069                    if (this.scribe.scanner.source[this.scribe.scanner.currentPosition] == '\n') {
4070                        this.scribe.scanner.currentPosition++;
4071                    }
4072                    this.scribe.lastNumberOfNewLines = 1;
4073            }
4074            return false;
4075        }
4076        
4077        /*
4078         * Print comments to get proper line number
4079         */

4080        this.scribe.printComment();
4081        int line = this.scribe.line;
4082        
4083        this.scribe.printModifiers(methodDeclaration.annotations, this);
4084        
4085        if (this.scribe.line > line) {
4086            // annotations introduced new line, but this is not a line wrapping
4087
// see 158267
4088
line = this.scribe.line;
4089        }
4090        this.scribe.space();
4091        
4092        TypeParameter[] typeParameters = methodDeclaration.typeParameters;
4093        if (typeParameters != null) {
4094            this.scribe.printNextToken(TerminalTokens.TokenNameLESS, this.preferences.insert_space_before_opening_angle_bracket_in_type_parameters);
4095            if (this.preferences.insert_space_after_opening_angle_bracket_in_type_parameters) {
4096                this.scribe.space();
4097            }
4098            int length = typeParameters.length;
4099            for (int i = 0; i < length - 1; i++) {
4100                typeParameters[i].traverse(this, methodDeclaration.scope);
4101                this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_type_parameters);
4102                if (this.preferences.insert_space_after_comma_in_type_parameters) {
4103                    this.scribe.space();
4104                }
4105            }
4106            typeParameters[length - 1].traverse(this, methodDeclaration.scope);
4107            if (isClosingGenericToken()) {
4108                this.scribe.printNextToken(CLOSING_GENERICS_EXPECTEDTOKENS, this.preferences.insert_space_before_closing_angle_bracket_in_type_parameters);
4109            }
4110            if (this.preferences.insert_space_after_closing_angle_bracket_in_type_parameters) {
4111                this.scribe.space();
4112            }
4113        }
4114        
4115        /*
4116         * Print the method return type
4117         */

4118        final TypeReference returnType = methodDeclaration.returnType;
4119        final MethodScope methodDeclarationScope = methodDeclaration.scope;
4120        
4121        if (returnType != null) {
4122            returnType.traverse(this, methodDeclarationScope);
4123        }
4124        /*
4125         * Print the method name
4126         */

4127        this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, true);
4128
4129        formatMethodArguments(
4130            methodDeclaration,
4131            this.preferences.insert_space_before_opening_paren_in_method_declaration,
4132            this.preferences.insert_space_between_empty_parens_in_method_declaration,
4133            this.preferences.insert_space_before_closing_paren_in_method_declaration,
4134            this.preferences.insert_space_after_opening_paren_in_method_declaration,
4135            this.preferences.insert_space_before_comma_in_method_declaration_parameters,
4136            this.preferences.insert_space_after_comma_in_method_declaration_parameters,
4137            this.preferences.alignment_for_parameters_in_method_declaration);
4138
4139        /*
4140         * Check for extra dimensions
4141         */

4142        int extraDimensions = getDimensions();
4143        if (extraDimensions != 0) {
4144             for (int i = 0; i < extraDimensions; i++) {
4145                this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET);
4146                this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET);
4147             }
4148        }
4149                
4150        formatThrowsClause(
4151            methodDeclaration,
4152            this.preferences.insert_space_before_comma_in_method_declaration_throws,
4153            this.preferences.insert_space_after_comma_in_method_declaration_throws,
4154            this.preferences.alignment_for_throws_clause_in_method_declaration);
4155
4156        if (!methodDeclaration.isNative() && !methodDeclaration.isAbstract() && ((methodDeclaration.modifiers & ExtraCompilerModifiers.AccSemicolonBody) == 0)) {
4157            /*
4158             * Method body
4159             */

4160            String JavaDoc method_declaration_brace = this.preferences.brace_position_for_method_declaration;
4161            formatLeftCurlyBrace(line, method_declaration_brace);
4162            formatOpeningBrace(method_declaration_brace, this.preferences.insert_space_before_opening_brace_in_method_declaration);
4163            final int numberOfBlankLinesAtBeginningOfMethodBody = this.preferences.blank_lines_at_beginning_of_method_body;
4164            if (numberOfBlankLinesAtBeginningOfMethodBody > 0) {
4165                this.scribe.printEmptyLines(numberOfBlankLinesAtBeginningOfMethodBody);
4166            }
4167            final Statement[] statements = methodDeclaration.statements;
4168            if (statements != null) {
4169                this.scribe.printNewLine();
4170                if (this.preferences.indent_statements_compare_to_body) {
4171                    this.scribe.indent();
4172                }
4173                formatStatements(methodDeclarationScope, statements, true);
4174                this.scribe.printComment();
4175                if (this.preferences.indent_statements_compare_to_body) {
4176                    this.scribe.unIndent();
4177                }
4178            } else if (this.preferences.insert_new_line_in_empty_method_body) {
4179                this.scribe.printNewLine();
4180                if (this.preferences.indent_statements_compare_to_body) {
4181                    this.scribe.indent();
4182                }
4183                this.scribe.printComment();
4184                if (this.preferences.indent_statements_compare_to_body) {
4185                    this.scribe.unIndent();
4186                }
4187            }
4188            this.scribe.printNextToken(TerminalTokens.TokenNameRBRACE);
4189            this.scribe.printTrailingComment();
4190            if (method_declaration_brace.equals(DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED)) {
4191                this.scribe.unIndent();
4192            }
4193        } else {
4194            // no method body
4195
this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
4196            this.scribe.printTrailingComment();
4197        }
4198        return false;
4199    }
4200    public boolean visit(NormalAnnotation annotation, BlockScope scope) {
4201        this.scribe.printNextToken(TerminalTokens.TokenNameAT);
4202        if (this.preferences.insert_space_after_at_in_annotation) {
4203            this.scribe.space();
4204        }
4205        this.scribe.printQualifiedReference(annotation.sourceEnd);
4206        this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_annotation);
4207        if (this.preferences.insert_space_after_opening_paren_in_annotation) {
4208            this.scribe.space();
4209        }
4210        MemberValuePair[] memberValuePairs = annotation.memberValuePairs;
4211        if (memberValuePairs != null) {
4212            int length = memberValuePairs.length;
4213            for (int i = 0; i < length - 1; i++) {
4214                memberValuePairs[i].traverse(this, scope);
4215                this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_annotation);
4216                if (this.preferences.insert_space_after_comma_in_annotation) {
4217                    this.scribe.space();
4218                }
4219            }
4220            memberValuePairs[length - 1].traverse(this, scope);
4221        }
4222        this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_annotation);
4223        return false;
4224    }
4225    /**
4226     * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.NullLiteral, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
4227     */

4228    public boolean visit(NullLiteral nullLiteral, BlockScope scope) {
4229
4230        final int numberOfParens = (nullLiteral.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
4231        if (numberOfParens > 0) {
4232            manageOpeningParenthesizedExpression(nullLiteral, numberOfParens);
4233        }
4234        this.scribe.printNextToken(TerminalTokens.TokenNamenull);
4235
4236        if (numberOfParens > 0) {
4237            manageClosingParenthesizedExpression(nullLiteral, numberOfParens);
4238        }
4239        return false;
4240    }
4241
4242
4243    /**
4244     * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.OR_OR_Expression, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
4245     */

4246    public boolean visit(OR_OR_Expression or_or_Expression, BlockScope scope) {
4247        return dumpBinaryExpression(or_or_Expression, TerminalTokens.TokenNameOR_OR, scope);
4248    }
4249    public boolean visit(
4250            ParameterizedQualifiedTypeReference parameterizedQualifiedTypeReference,
4251            BlockScope scope) {
4252        final int numberOfParens = (parameterizedQualifiedTypeReference.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
4253        if (numberOfParens > 0) {
4254            manageOpeningParenthesizedExpression(parameterizedQualifiedTypeReference, numberOfParens);
4255        }
4256        TypeReference[][] typeArguments = parameterizedQualifiedTypeReference.typeArguments;
4257        int length = typeArguments.length;
4258        for (int i = 0; i < length; i++) {
4259            this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier);
4260            TypeReference[] typeArgument = typeArguments[i];
4261            if (typeArgument != null) {
4262                this.scribe.printNextToken(TerminalTokens.TokenNameLESS, this.preferences.insert_space_before_opening_angle_bracket_in_parameterized_type_reference);
4263                if (this.preferences.insert_space_after_opening_angle_bracket_in_parameterized_type_reference) {
4264                    this.scribe.space();
4265                }
4266                int typeArgumentLength = typeArgument.length;
4267                for (int j = 0; j < typeArgumentLength - 1; j++) {
4268                    typeArgument[j].traverse(this, scope);
4269                    this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_parameterized_type_reference);
4270                    if (this.preferences.insert_space_after_comma_in_parameterized_type_reference) {
4271                        this.scribe.space();
4272                    }
4273                }
4274                typeArgument[typeArgumentLength - 1].traverse(this, scope);
4275                if (isClosingGenericToken()) {
4276                    this.scribe.printNextToken(CLOSING_GENERICS_EXPECTEDTOKENS, this.preferences.insert_space_before_closing_angle_bracket_in_parameterized_type_reference);
4277                }
4278            }
4279            if (i < length - 1) {
4280                this.scribe.printNextToken(TerminalTokens.TokenNameDOT);
4281            }
4282        }
4283        int dimensions = getDimensions();
4284        if (dimensions != 0 && dimensions <= parameterizedQualifiedTypeReference.dimensions()) {
4285            if (this.preferences.insert_space_before_opening_bracket_in_array_type_reference) {
4286                this.scribe.space();
4287            }
4288            for (int i = 0; i < dimensions; i++) {
4289                this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET);
4290                if (this.preferences.insert_space_between_brackets_in_array_type_reference) {
4291                    this.scribe.space();
4292                }
4293                this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET);
4294            }
4295        }
4296        if (numberOfParens > 0) {
4297            manageClosingParenthesizedExpression(parameterizedQualifiedTypeReference, numberOfParens);
4298        }
4299        return false;
4300    }
4301    public boolean visit(
4302            ParameterizedQualifiedTypeReference parameterizedQualifiedTypeReference,
4303            ClassScope scope) {
4304        final int numberOfParens = (parameterizedQualifiedTypeReference.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
4305        if (numberOfParens > 0) {
4306            manageOpeningParenthesizedExpression(parameterizedQualifiedTypeReference, numberOfParens);
4307        }
4308        TypeReference[][] typeArguments = parameterizedQualifiedTypeReference.typeArguments;
4309        int length = typeArguments.length;
4310        for (int i = 0; i < length; i++) {
4311            this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier);
4312            TypeReference[] typeArgument = typeArguments[i];
4313            if (typeArgument != null) {
4314                this.scribe.printNextToken(TerminalTokens.TokenNameLESS, this.preferences.insert_space_before_opening_angle_bracket_in_parameterized_type_reference);
4315                if (this.preferences.insert_space_after_opening_angle_bracket_in_parameterized_type_reference) {
4316                    this.scribe.space();
4317                }
4318                int typeArgumentLength = typeArgument.length;
4319                for (int j = 0; j < typeArgumentLength - 1; j++) {
4320                    typeArgument[j].traverse(this, scope);
4321                    this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_parameterized_type_reference);
4322                    if (this.preferences.insert_space_after_comma_in_parameterized_type_reference) {
4323                        this.scribe.space();
4324                    }
4325                }
4326                typeArgument[typeArgumentLength - 1].traverse(this, scope);
4327                if (isClosingGenericToken()) {
4328                    this.scribe.printNextToken(CLOSING_GENERICS_EXPECTEDTOKENS, this.preferences.insert_space_before_closing_angle_bracket_in_parameterized_type_reference);
4329                }
4330            }
4331            if (i < length - 1) {
4332                this.scribe.printNextToken(TerminalTokens.TokenNameDOT);
4333            }
4334        }
4335        int dimensions = getDimensions();
4336        if (dimensions != 0 && dimensions <= parameterizedQualifiedTypeReference.dimensions()) {
4337            if (this.preferences.insert_space_before_opening_bracket_in_array_type_reference) {
4338                this.scribe.space();
4339            }
4340            for (int i = 0; i < dimensions; i++) {
4341                this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET);
4342                if (this.preferences.insert_space_between_brackets_in_array_type_reference) {
4343                    this.scribe.space();
4344                }
4345                this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET);
4346            }
4347        }
4348        if (numberOfParens > 0) {
4349            manageClosingParenthesizedExpression(parameterizedQualifiedTypeReference, numberOfParens);
4350        }
4351        return false;
4352    }
4353    public boolean visit(
4354            ParameterizedSingleTypeReference parameterizedSingleTypeReference,
4355            BlockScope scope) {
4356        final int numberOfParens = (parameterizedSingleTypeReference.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
4357        if (numberOfParens > 0) {
4358            manageOpeningParenthesizedExpression(parameterizedSingleTypeReference, numberOfParens);
4359        }
4360        this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier);
4361
4362        this.scribe.printNextToken(TerminalTokens.TokenNameLESS, this.preferences.insert_space_before_opening_angle_bracket_in_parameterized_type_reference);
4363        if (this.preferences.insert_space_after_opening_angle_bracket_in_parameterized_type_reference) {
4364            this.scribe.space();
4365        }
4366        TypeReference[] typeArguments = parameterizedSingleTypeReference.typeArguments;
4367        int typeArgumentsLength = typeArguments.length;
4368        for (int i = 0; i < typeArgumentsLength - 1; i++) {
4369            typeArguments[i].traverse(this, scope);
4370            this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_parameterized_type_reference);
4371            if (this.preferences.insert_space_after_comma_in_parameterized_type_reference) {
4372                this.scribe.space();
4373            }
4374        }
4375        typeArguments[typeArgumentsLength - 1].traverse(this, scope);
4376        if (isClosingGenericToken()) {
4377            this.scribe.printNextToken(CLOSING_GENERICS_EXPECTEDTOKENS, this.preferences.insert_space_before_closing_angle_bracket_in_parameterized_type_reference);
4378        }
4379        int dimensions = getDimensions();
4380        if (dimensions != 0 && dimensions <= parameterizedSingleTypeReference.dimensions()) {
4381            if (this.preferences.insert_space_before_opening_bracket_in_array_type_reference) {
4382                this.scribe.space();
4383            }
4384            for (int i = 0; i < dimensions; i++) {
4385                this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET);
4386                if (this.preferences.insert_space_between_brackets_in_array_type_reference) {
4387                    this.scribe.space();
4388                }
4389                this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET);
4390            }
4391        }
4392        if (numberOfParens > 0) {
4393            manageClosingParenthesizedExpression(parameterizedSingleTypeReference, numberOfParens);
4394        }
4395        return false;
4396    }
4397    public boolean visit(
4398            ParameterizedSingleTypeReference parameterizedSingleTypeReference,
4399            ClassScope scope) {
4400        final int numberOfParens = (parameterizedSingleTypeReference.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
4401        if (numberOfParens > 0) {
4402            manageOpeningParenthesizedExpression(parameterizedSingleTypeReference, numberOfParens);
4403        }
4404        this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier);
4405
4406        this.scribe.printNextToken(TerminalTokens.TokenNameLESS, this.preferences.insert_space_before_opening_angle_bracket_in_parameterized_type_reference);
4407        if (this.preferences.insert_space_after_opening_angle_bracket_in_parameterized_type_reference) {
4408            this.scribe.space();
4409        }
4410        TypeReference[] typeArguments = parameterizedSingleTypeReference.typeArguments;
4411        int typeArgumentsLength = typeArguments.length;
4412        for (int i = 0; i < typeArgumentsLength - 1; i++) {
4413            typeArguments[i].traverse(this, scope);
4414            this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_parameterized_type_reference);
4415            if (this.preferences.insert_space_after_comma_in_parameterized_type_reference) {
4416                this.scribe.space();
4417            }
4418        }
4419        typeArguments[typeArgumentsLength - 1].traverse(this, scope);
4420        if (isClosingGenericToken()) {
4421            this.scribe.printNextToken(CLOSING_GENERICS_EXPECTEDTOKENS, this.preferences.insert_space_before_closing_angle_bracket_in_parameterized_type_reference);
4422        }
4423        int dimensions = getDimensions();
4424        if (dimensions != 0 && dimensions <= parameterizedSingleTypeReference.dimensions()) {
4425            if (this.preferences.insert_space_before_opening_bracket_in_array_type_reference) {
4426                this.scribe.space();
4427            }
4428            for (int i = 0; i < dimensions; i++) {
4429                this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET);
4430                if (this.preferences.insert_space_between_brackets_in_array_type_reference) {
4431                    this.scribe.space();
4432                }
4433                this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET);
4434            }
4435        }
4436        if (numberOfParens > 0) {
4437            manageClosingParenthesizedExpression(parameterizedSingleTypeReference, numberOfParens);
4438        }
4439        return false;
4440    }
4441    
4442    /**
4443     * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.PostfixExpression, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
4444     */

4445    public boolean visit(
4446        PostfixExpression postfixExpression,
4447        BlockScope scope) {
4448
4449        final int numberOfParens = (postfixExpression.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
4450        if (numberOfParens > 0) {
4451            manageOpeningParenthesizedExpression(postfixExpression, numberOfParens);
4452        }
4453        postfixExpression.lhs.traverse(this, scope);
4454        int operator = postfixExpression.operator == OperatorIds.PLUS
4455            ? TerminalTokens.TokenNamePLUS_PLUS : TerminalTokens.TokenNameMINUS_MINUS;
4456        this.scribe.printNextToken(operator, this.preferences.insert_space_before_postfix_operator);
4457        if (this.preferences.insert_space_after_postfix_operator) {
4458            this.scribe.space();
4459        }
4460        if (numberOfParens > 0) {
4461            manageClosingParenthesizedExpression(postfixExpression, numberOfParens);
4462        }
4463        return false;
4464    }
4465
4466    /**
4467     * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.PrefixExpression, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
4468     */

4469    public boolean visit(PrefixExpression prefixExpression, BlockScope scope) {
4470
4471        final int numberOfParens = (prefixExpression.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
4472        if (numberOfParens > 0) {
4473            manageOpeningParenthesizedExpression(prefixExpression, numberOfParens);
4474        }
4475        int operator = prefixExpression.operator == OperatorIds.PLUS
4476            ? TerminalTokens.TokenNamePLUS_PLUS : TerminalTokens.TokenNameMINUS_MINUS;
4477        this.scribe.printNextToken(operator, this.preferences.insert_space_before_prefix_operator);
4478        if (this.preferences.insert_space_after_prefix_operator) {
4479            this.scribe.space();
4480        }
4481        prefixExpression.lhs.traverse(this, scope);
4482        if (numberOfParens > 0) {
4483            manageClosingParenthesizedExpression(prefixExpression, numberOfParens);
4484        }
4485        return false;
4486    }
4487    
4488    /**
4489     * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.QualifiedAllocationExpression, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
4490     */

4491    public boolean visit(
4492        QualifiedAllocationExpression qualifiedAllocationExpression,
4493        BlockScope scope) {
4494            
4495        final int numberOfParens = (qualifiedAllocationExpression.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
4496        if (numberOfParens > 0) {
4497            manageOpeningParenthesizedExpression(qualifiedAllocationExpression, numberOfParens);
4498        }
4499        final Expression enclosingInstance = qualifiedAllocationExpression.enclosingInstance;
4500        if (enclosingInstance != null) {
4501            enclosingInstance.traverse(this, scope);
4502            this.scribe.printNextToken(TerminalTokens.TokenNameDOT);
4503        }
4504        
4505        this.scribe.printNextToken(TerminalTokens.TokenNamenew);
4506        // used for the new line on wrap style of formatting
4507
TypeReference[] typeArguments = qualifiedAllocationExpression.typeArguments;
4508        if (typeArguments != null) {
4509                this.scribe.printNextToken(TerminalTokens.TokenNameLESS, this.preferences.insert_space_before_opening_angle_bracket_in_type_arguments);
4510                if (this.preferences.insert_space_after_opening_angle_bracket_in_type_arguments) {
4511                    this.scribe.space();
4512                }
4513                int length = typeArguments.length;
4514                for (int i = 0; i < length - 1; i++) {
4515                    typeArguments[i].traverse(this, scope);
4516                    this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_type_arguments);
4517                    if (this.preferences.insert_space_after_comma_in_type_arguments) {
4518                        this.scribe.space();
4519                    }
4520                }
4521                typeArguments[length - 1].traverse(this, scope);
4522                if (isClosingGenericToken()) {
4523                    this.scribe.printNextToken(CLOSING_GENERICS_EXPECTEDTOKENS, this.preferences.insert_space_before_closing_angle_bracket_in_type_arguments);
4524                }
4525                if (this.preferences.insert_space_after_closing_angle_bracket_in_type_arguments) {
4526                    this.scribe.space();
4527                }
4528        } else {
4529            this.scribe.space();
4530        }
4531
4532        final int line = this.scribe.line;
4533        qualifiedAllocationExpression.type.traverse(this, scope);
4534        
4535        this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_method_invocation);
4536
4537        final Expression[] arguments = qualifiedAllocationExpression.arguments;
4538        if (arguments != null) {
4539            if (this.preferences.insert_space_after_opening_paren_in_method_invocation) {
4540                this.scribe.space();
4541            }
4542            int argumentLength = arguments.length;
4543            Alignment argumentsAlignment =this.scribe.createAlignment(
4544                    "allocation",//$NON-NLS-1$
4545
this.preferences.alignment_for_arguments_in_qualified_allocation_expression,
4546                    argumentLength,
4547                    this.scribe.scanner.currentPosition);
4548            this.scribe.enterAlignment(argumentsAlignment);
4549            boolean ok = false;
4550            do {
4551                try {
4552                    for (int i = 0; i < argumentLength; i++) {
4553                        if (i > 0) {
4554                            this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_allocation_expression);
4555                            this.scribe.printTrailingComment();
4556                        }
4557                        this.scribe.alignFragment(argumentsAlignment, i);
4558                        if (i > 0 && this.preferences.insert_space_after_comma_in_allocation_expression) {
4559                            this.scribe.space();
4560                        }
4561                        arguments[i].traverse(this, scope);
4562                    }
4563                    ok = true;
4564                } catch (AlignmentException e) {
4565                    this.scribe.redoAlignment(e);
4566                }
4567            } while (!ok);
4568            this.scribe.exitAlignment(argumentsAlignment, true);
4569            this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_method_invocation);
4570        } else {
4571            this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_between_empty_parens_in_method_invocation);
4572        }
4573        final TypeDeclaration anonymousType = qualifiedAllocationExpression.anonymousType;
4574        if (anonymousType != null) {
4575            formatLeftCurlyBrace(line, this.preferences.brace_position_for_anonymous_type_declaration);
4576            formatAnonymousTypeDeclaration(anonymousType);
4577        }
4578        if (numberOfParens > 0) {
4579            manageClosingParenthesizedExpression(qualifiedAllocationExpression, numberOfParens);
4580        }
4581        return false;
4582    }
4583
4584    /**
4585     * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
4586     */

4587    public boolean visit(
4588        QualifiedNameReference qualifiedNameReference,
4589        BlockScope scope) {
4590
4591        final int numberOfParens = (qualifiedNameReference.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
4592        if (numberOfParens > 0) {
4593            manageOpeningParenthesizedExpression(qualifiedNameReference, numberOfParens);
4594        }
4595        this.scribe.printQualifiedReference(qualifiedNameReference.sourceEnd);
4596
4597        if (numberOfParens > 0) {
4598            manageClosingParenthesizedExpression(qualifiedNameReference, numberOfParens);
4599        }
4600        return false;
4601    }
4602
4603    /**
4604     * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.QualifiedSuperReference, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
4605     */

4606    public boolean visit(
4607        QualifiedSuperReference qualifiedSuperReference,
4608        BlockScope scope) {
4609
4610        final int numberOfParens = (qualifiedSuperReference.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
4611        if (numberOfParens > 0) {
4612            manageOpeningParenthesizedExpression(qualifiedSuperReference, numberOfParens);
4613        }
4614        qualifiedSuperReference.qualification.traverse(this, scope);
4615        this.scribe.printNextToken(TerminalTokens.TokenNameDOT);
4616        this.scribe.printNextToken(TerminalTokens.TokenNamesuper);
4617        
4618        if (numberOfParens > 0) {
4619            manageClosingParenthesizedExpression(qualifiedSuperReference, numberOfParens);
4620        }
4621        return false;
4622    }
4623
4624    /**
4625     * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.QualifiedThisReference, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
4626     */

4627    public boolean visit(
4628        QualifiedThisReference qualifiedThisReference,
4629        BlockScope scope) {
4630
4631        final int numberOfParens = (qualifiedThisReference.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
4632        if (numberOfParens > 0) {
4633            manageOpeningParenthesizedExpression(qualifiedThisReference, numberOfParens);
4634        }
4635        qualifiedThisReference.qualification.traverse(this, scope);
4636        this.scribe.printNextToken(TerminalTokens.TokenNameDOT);
4637        this.scribe.printNextToken(TerminalTokens.TokenNamethis);
4638        
4639        if (numberOfParens > 0) {
4640            manageClosingParenthesizedExpression(qualifiedThisReference, numberOfParens);
4641        }
4642        return false;
4643    }
4644
4645    /**
4646     * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
4647     */

4648    public boolean visit(
4649        QualifiedTypeReference qualifiedTypeReference,
4650        BlockScope scope) {
4651
4652        final int numberOfParens = (qualifiedTypeReference.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
4653        if (numberOfParens > 0) {
4654            manageOpeningParenthesizedExpression(qualifiedTypeReference, numberOfParens);
4655        }
4656        this.scribe.printQualifiedReference(qualifiedTypeReference.sourceEnd);
4657        
4658        if (numberOfParens > 0) {
4659            manageClosingParenthesizedExpression(qualifiedTypeReference, numberOfParens);
4660        }
4661        return false;
4662    }
4663
4664    /**
4665     * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference, org.eclipse.jdt.internal.compiler.lookup.ClassScope)
4666     */

4667    public boolean visit(
4668        QualifiedTypeReference qualifiedTypeReference,
4669        ClassScope scope) {
4670
4671            final int numberOfParens = (qualifiedTypeReference.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
4672            if (numberOfParens > 0) {
4673                manageOpeningParenthesizedExpression(qualifiedTypeReference, numberOfParens);
4674            }
4675            this.scribe.printQualifiedReference(qualifiedTypeReference.sourceEnd);
4676            
4677            if (numberOfParens > 0) {
4678                manageClosingParenthesizedExpression(qualifiedTypeReference, numberOfParens);
4679            }
4680            return false;
4681    }
4682
4683    /**
4684     * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.ReturnStatement, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
4685     */

4686    public boolean visit(ReturnStatement returnStatement, BlockScope scope) {
4687        
4688        this.scribe.printNextToken(TerminalTokens.TokenNamereturn);
4689        final Expression expression = returnStatement.expression;
4690        if (expression != null) {
4691            final int numberOfParens = (expression.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
4692            if ((numberOfParens != 0 && this.preferences.insert_space_before_parenthesized_expression_in_return)
4693                    || numberOfParens == 0) {
4694                this.scribe.space();
4695            }
4696            expression.traverse(this, scope);
4697        }
4698        /*
4699         * Print the semi-colon
4700         */

4701        this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
4702        this.scribe.printTrailingComment();
4703        return false;
4704    }
4705    public boolean visit(SingleMemberAnnotation annotation, BlockScope scope) {
4706        this.scribe.printNextToken(TerminalTokens.TokenNameAT);
4707        if (this.preferences.insert_space_after_at_in_annotation) {
4708            this.scribe.space();
4709        }
4710        this.scribe.printQualifiedReference(annotation.sourceEnd);
4711        this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_annotation);
4712        if (this.preferences.insert_space_after_opening_paren_in_annotation) {
4713            this.scribe.space();
4714        }
4715        annotation.memberValue.traverse(this, scope);
4716        this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_annotation);
4717        return false;
4718    }
4719    /**
4720     * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.SingleNameReference, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
4721     */

4722    public boolean visit(SingleNameReference singleNameReference, BlockScope scope) {
4723
4724        final int numberOfParens = (singleNameReference.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
4725        if (numberOfParens > 0) {
4726            manageOpeningParenthesizedExpression(singleNameReference, numberOfParens);
4727        }
4728        this.scribe.printNextToken(SINGLETYPEREFERENCE_EXPECTEDTOKENS);
4729        
4730        if (numberOfParens > 0) {
4731            manageClosingParenthesizedExpression(singleNameReference, numberOfParens);
4732        }
4733        return false;
4734    }
4735
4736    /**
4737     * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.SingleTypeReference, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
4738     */

4739    public boolean visit(
4740        SingleTypeReference singleTypeReference,
4741        BlockScope scope) {
4742
4743        final int numberOfParens = (singleTypeReference.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
4744        if (numberOfParens > 0) {
4745            manageOpeningParenthesizedExpression(singleTypeReference, numberOfParens);
4746        }
4747        this.scribe.printNextToken(SINGLETYPEREFERENCE_EXPECTEDTOKENS);
4748
4749        if (numberOfParens > 0) {
4750            manageClosingParenthesizedExpression(singleTypeReference, numberOfParens);
4751        }
4752        return false;
4753    }
4754
4755    /**
4756     * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.SingleTypeReference, org.eclipse.jdt.internal.compiler.lookup.ClassScope)
4757     */

4758    public boolean visit(
4759        SingleTypeReference singleTypeReference,
4760        ClassScope scope) {
4761
4762        final int numberOfParens = (singleTypeReference.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
4763        if (numberOfParens > 0) {
4764            manageOpeningParenthesizedExpression(singleTypeReference, numberOfParens);
4765        }
4766        this.scribe.printNextToken(SINGLETYPEREFERENCE_EXPECTEDTOKENS);
4767
4768        if (numberOfParens > 0) {
4769            manageClosingParenthesizedExpression(singleTypeReference, numberOfParens);
4770        }
4771        return false;
4772    }
4773
4774    /**
4775     * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.StringLiteral, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
4776     */

4777    public boolean visit(StringLiteral stringLiteral, BlockScope scope) {
4778        final int numberOfParens = (stringLiteral.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
4779        if (numberOfParens > 0) {
4780            manageOpeningParenthesizedExpression(stringLiteral, numberOfParens);
4781        }
4782        this.scribe.checkNLSTag(stringLiteral.sourceStart);
4783        this.scribe.printNextToken(TerminalTokens.TokenNameStringLiteral);
4784        this.scribe.printTrailingComment();
4785        if (numberOfParens > 0) {
4786            manageClosingParenthesizedExpression(stringLiteral, numberOfParens);
4787        }
4788        return false;
4789    }
4790
4791    /**
4792     * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.NullLiteral, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
4793     */

4794    public boolean visit(StringLiteralConcatenation stringLiteral, BlockScope scope) {
4795        final int numberOfParens = (stringLiteral.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
4796        if (numberOfParens > 0) {
4797            manageOpeningParenthesizedExpression(stringLiteral, numberOfParens);
4798        }
4799
4800        this.scribe.printComment();
4801        ASTNode[] fragments = stringLiteral.literals;
4802        int fragmentsSize = stringLiteral.counter;
4803        Alignment binaryExpressionAlignment = this.scribe.createAlignment("binaryExpressionAlignment", this.preferences.alignment_for_binary_expression, Alignment.R_OUTERMOST, fragmentsSize, this.scribe.scanner.currentPosition); //$NON-NLS-1$
4804
this.scribe.enterAlignment(binaryExpressionAlignment);
4805        boolean ok = false;
4806        do {
4807            try {
4808                for (int i = 0; i < fragmentsSize - 1; i++) {
4809                    ASTNode fragment = fragments[i];
4810                    fragment.traverse(this, scope);
4811                    this.scribe.printTrailingComment();
4812                    if (this.scribe.lastNumberOfNewLines == 1) {
4813                        // a new line has been inserted by printTrailingComment()
4814
this.scribe.indentationLevel = binaryExpressionAlignment.breakIndentationLevel;
4815                    }
4816                    this.scribe.alignFragment(binaryExpressionAlignment, i);
4817                    this.scribe.printNextToken(TerminalTokens.TokenNamePLUS, this.preferences.insert_space_before_binary_operator);
4818                    if (this.preferences.insert_space_after_binary_operator) {
4819                        this.scribe.space();
4820                    }
4821                }
4822                fragments[fragmentsSize - 1].traverse(this, scope);
4823                this.scribe.printTrailingComment();
4824                ok = true;
4825            } catch(AlignmentException e){
4826                this.scribe.redoAlignment(e);
4827            }
4828        } while (!ok);
4829        this.scribe.exitAlignment(binaryExpressionAlignment, true);
4830    
4831        if (numberOfParens > 0) {
4832            manageClosingParenthesizedExpression(stringLiteral, numberOfParens);
4833        }
4834        return false;
4835    }
4836
4837    /**
4838     * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.SuperReference, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
4839     */

4840    public boolean visit(SuperReference superReference, BlockScope scope) {
4841
4842        final int numberOfParens = (superReference.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
4843        if (numberOfParens > 0) {
4844            manageOpeningParenthesizedExpression(superReference, numberOfParens);
4845        }
4846        this.scribe.printNextToken(TerminalTokens.TokenNamesuper);
4847
4848        if (numberOfParens > 0) {
4849            manageClosingParenthesizedExpression(superReference, numberOfParens);
4850        }
4851        return false;
4852    }
4853
4854    /**
4855     * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.SwitchStatement, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
4856     */

4857    public boolean visit(SwitchStatement switchStatement, BlockScope scope) {
4858        this.scribe.printNextToken(TerminalTokens.TokenNameswitch);
4859        this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_switch);
4860        
4861        if (this.preferences.insert_space_after_opening_paren_in_switch) {
4862            this.scribe.space();
4863        }
4864        
4865        switchStatement.expression.traverse(this, scope);
4866        this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_switch);
4867        /*
4868         * Type body
4869         */

4870        String JavaDoc switch_brace = this.preferences.brace_position_for_switch;
4871        formatOpeningBrace(switch_brace, this.preferences.insert_space_before_opening_brace_in_switch);
4872        this.scribe.printNewLine();
4873
4874        if (this.preferences.indent_switchstatements_compare_to_switch) {
4875            this.scribe.indent();
4876        }
4877        final Statement[] statements = switchStatement.statements;
4878        boolean wasACase = false;
4879        boolean wasAStatement = false;
4880        if (statements != null) {
4881            int statementsLength = statements.length;
4882            for (int i = 0; i < statementsLength; i++) {
4883                final Statement statement = statements[i];
4884                if (statement instanceof CaseStatement) {
4885                    if (wasACase) {
4886                        this.scribe.printNewLine();
4887                    }
4888                    if ((wasACase && this.preferences.indent_switchstatements_compare_to_cases)
4889                        || (wasAStatement && this.preferences.indent_switchstatements_compare_to_cases)) {
4890                        this.scribe.unIndent();
4891                    }
4892                    statement.traverse(this, scope);
4893                    this.scribe.printTrailingComment();
4894                    wasACase = true;
4895                    wasAStatement = false;
4896                    if (this.preferences.indent_switchstatements_compare_to_cases) {
4897                        this.scribe.indent();
4898                    }
4899                } else if (statement instanceof BreakStatement) {
4900                    if (this.preferences.indent_breaks_compare_to_cases) {
4901                        if (wasAStatement && !this.preferences.indent_switchstatements_compare_to_cases) {
4902                            this.scribe.indent();
4903                        }
4904                    } else {
4905                        if (wasAStatement) {
4906                            if (this.preferences.indent_switchstatements_compare_to_cases) {
4907                                this.scribe.unIndent();
4908                            }
4909                        }
4910                        if (wasACase && this.preferences.indent_switchstatements_compare_to_cases) {
4911                            this.scribe.unIndent();
4912                        }
4913                    }
4914                    if (wasACase) {
4915                        this.scribe.printNewLine();
4916                    }
4917                    statement.traverse(this, scope);
4918                    if (this.preferences.indent_breaks_compare_to_cases) {
4919                        this.scribe.unIndent();
4920                    }
4921                    wasACase = false;
4922                    wasAStatement = false;
4923                } else if (statement instanceof Block) {
4924                    String JavaDoc bracePosition;
4925                    if (wasACase) {
4926                        if (this.preferences.indent_switchstatements_compare_to_cases) {
4927                            this.scribe.unIndent();
4928                        }
4929                        bracePosition = this.preferences.brace_position_for_block_in_case;
4930                        formatBlock((Block) statement, scope, bracePosition, this.preferences.insert_space_after_colon_in_case);
4931                        if (this.preferences.indent_switchstatements_compare_to_cases) {
4932                            this.scribe.indent();
4933                        }
4934                    } else {
4935                        bracePosition = this.preferences.brace_position_for_block;
4936                        formatBlock((Block) statement, scope, bracePosition, this.preferences.insert_space_before_opening_brace_in_block);
4937                    }
4938                    wasAStatement = true;
4939                    wasACase = false;
4940                } else {
4941                    this.scribe.printNewLine();
4942                    statement.traverse(this, scope);
4943                    wasAStatement = true;
4944                    wasACase = false;
4945                }
4946                if (statement instanceof Expression) {
4947                    /*
4948                     * Print the semi-colon
4949                     */

4950                    this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
4951                    this.scribe.printTrailingComment();
4952                    this.scribe.printNewLine();
4953                } else if (statement instanceof LocalDeclaration) {
4954                    LocalDeclaration currentLocal = (LocalDeclaration) statement;
4955                    if (i < (statementsLength - 1)) {
4956                        /*
4957                         * We need to check that the next statement is a local declaration
4958                         */

4959                        if (statements[i + 1] instanceof LocalDeclaration) {
4960                            LocalDeclaration nextLocal = (LocalDeclaration) statements[i + 1];
4961                            if (currentLocal.declarationSourceStart != nextLocal.declarationSourceStart) {
4962                                /*
4963                                 * Print the semi-colon
4964                                 */

4965                                this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
4966                                this.scribe.printTrailingComment();
4967                                this.scribe.printNewLine();
4968                            }
4969                        } else {
4970                            /*
4971                             * Print the semi-colon
4972                             */

4973                            this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
4974                            this.scribe.printTrailingComment();
4975                            this.scribe.printNewLine();
4976                        }
4977                    } else {
4978                        /*
4979                         * Print the semi-colon
4980                         */

4981                        this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
4982                        this.scribe.printTrailingComment();
4983                        this.scribe.printNewLine();
4984                    }
4985                } else if (!wasACase) {
4986                    this.scribe.printNewLine();
4987                }
4988                this.scribe.printComment();
4989            }
4990        }
4991        
4992        if ((wasACase || wasAStatement) && this.preferences.indent_switchstatements_compare_to_cases) {
4993            this.scribe.unIndent();
4994        }
4995        if (this.preferences.indent_switchstatements_compare_to_switch) {
4996            this.scribe.unIndent();
4997        }
4998        this.scribe.printNewLine();
4999        this.scribe.printNextToken(TerminalTokens.TokenNameRBRACE);
5000        this.scribe.printTrailingComment();
5001        if (switch_brace.equals(DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED)) {
5002            this.scribe.unIndent();
5003        }
5004        return false;
5005    }
5006
5007    /**
5008     * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.SynchronizedStatement, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
5009     */

5010    public boolean visit(
5011        SynchronizedStatement synchronizedStatement,
5012        BlockScope scope) {
5013        
5014        this.scribe.printNextToken(TerminalTokens.TokenNamesynchronized);
5015
5016        final int line = this.scribe.line;
5017
5018        this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_synchronized);
5019        
5020        if (this.preferences.insert_space_after_opening_paren_in_synchronized) {
5021            this.scribe.space();
5022        }
5023        synchronizedStatement.expression.traverse(this, scope);
5024    
5025        this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_synchronized);
5026        
5027        formatLeftCurlyBrace(line, this.preferences.brace_position_for_block);
5028        synchronizedStatement.block.traverse(this, scope);
5029        return false;
5030    }
5031    /**
5032     * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.ThisReference, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
5033     */

5034    public boolean visit(ThisReference thisReference, BlockScope scope) {
5035        
5036        if (!thisReference.isImplicitThis()) {
5037            final int numberOfParens = (thisReference.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
5038            if (numberOfParens > 0) {
5039                manageOpeningParenthesizedExpression(thisReference, numberOfParens);
5040            }
5041            this.scribe.printNextToken(TerminalTokens.TokenNamethis);
5042            
5043            if (numberOfParens > 0) {
5044                manageClosingParenthesizedExpression(thisReference, numberOfParens);
5045            }
5046        }
5047        return false;
5048    }
5049
5050    /**
5051     * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.ThrowStatement, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
5052     */

5053    public boolean visit(ThrowStatement throwStatement, BlockScope scope) {
5054
5055        this.scribe.printNextToken(TerminalTokens.TokenNamethrow);
5056        Expression expression = throwStatement.exception;
5057        final int numberOfParens = (expression.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
5058        if ((numberOfParens > 0 && this.preferences.insert_space_before_parenthesized_expression_in_throw)
5059                || numberOfParens == 0) {
5060            this.scribe.space();
5061        }
5062        expression.traverse(this, scope);
5063        /*
5064         * Print the semi-colon
5065         */

5066        this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
5067        this.scribe.printTrailingComment();
5068        return false;
5069    }
5070
5071    /**
5072     * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.TrueLiteral, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
5073     */

5074    public boolean visit(TrueLiteral trueLiteral, BlockScope scope) {
5075
5076        final int numberOfParens = (trueLiteral.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
5077        if (numberOfParens > 0) {
5078            manageOpeningParenthesizedExpression(trueLiteral, numberOfParens);
5079        }
5080        this.scribe.printNextToken(TerminalTokens.TokenNametrue);
5081
5082        if (numberOfParens > 0) {
5083            manageClosingParenthesizedExpression(trueLiteral, numberOfParens);
5084        }
5085        return false;
5086    }
5087
5088    /**
5089     * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.TryStatement, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
5090     */

5091    public boolean visit(TryStatement tryStatement, BlockScope scope) {
5092
5093        this.scribe.printNextToken(TerminalTokens.TokenNametry);
5094        tryStatement.tryBlock.traverse(this, scope);
5095        if (tryStatement.catchArguments != null) {
5096            for (int i = 0, max = tryStatement.catchBlocks.length; i < max; i++) {
5097                if (this.preferences.insert_new_line_before_catch_in_try_statement) {
5098                    this.scribe.printNewLine();
5099                }
5100                this.scribe.printNextToken(TerminalTokens.TokenNamecatch, this.preferences.insert_space_after_closing_brace_in_block);
5101                final int line = this.scribe.line;
5102                this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_catch);
5103                
5104                if (this.preferences.insert_space_after_opening_paren_in_catch) {
5105                    this.scribe.space();
5106                }
5107                
5108                tryStatement.catchArguments[i].traverse(this, scope);
5109            
5110                this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_catch);
5111                
5112                formatLeftCurlyBrace(line, this.preferences.brace_position_for_block);
5113                tryStatement.catchBlocks[i].traverse(this, scope);
5114            }
5115        }
5116        if (tryStatement.finallyBlock != null) {
5117            if (this.preferences.insert_new_line_before_finally_in_try_statement) {
5118                this.scribe.printNewLine();
5119            }
5120            this.scribe.printNextToken(TerminalTokens.TokenNamefinally, this.preferences.insert_space_after_closing_brace_in_block);
5121            tryStatement.finallyBlock.traverse(this, scope);
5122        }
5123        return false;
5124    }
5125
5126    /**
5127     * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.TypeDeclaration, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
5128     */

5129    public boolean visit(
5130        TypeDeclaration localTypeDeclaration,
5131        BlockScope scope) {
5132
5133            format(localTypeDeclaration);
5134            return false;
5135    }
5136
5137    /**
5138     * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.TypeDeclaration, org.eclipse.jdt.internal.compiler.lookup.ClassScope)
5139     */

5140    public boolean visit(TypeDeclaration memberTypeDeclaration, ClassScope scope) {
5141        format(memberTypeDeclaration);
5142        return false;
5143    }
5144    
5145    /**
5146     * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.TypeDeclaration, org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope)
5147     */

5148    public boolean visit(
5149        TypeDeclaration typeDeclaration,
5150        CompilationUnitScope scope) {
5151
5152        format(typeDeclaration);
5153        return false;
5154    }
5155    public boolean visit(TypeParameter typeParameter, BlockScope scope) {
5156        this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier);
5157        if (typeParameter.type != null) {
5158            this.scribe.space();
5159            this.scribe.printNextToken(TerminalTokens.TokenNameextends, true);
5160            this.scribe.space();
5161            typeParameter.type.traverse(this, scope);
5162        }
5163        final TypeReference[] bounds = typeParameter.bounds;
5164        if (bounds != null) {
5165            this.scribe.printNextToken(TerminalTokens.TokenNameAND, this.preferences.insert_space_before_and_in_type_parameter);
5166            if (this.preferences.insert_space_after_and_in_type_parameter) {
5167                this.scribe.space();
5168            }
5169            int boundsLength = bounds.length;
5170            for (int i = 0; i < boundsLength - 1; i++) {
5171                bounds[i].traverse(this, scope);
5172                this.scribe.printNextToken(TerminalTokens.TokenNameAND, this.preferences.insert_space_before_and_in_type_parameter);
5173                if (this.preferences.insert_space_after_and_in_type_parameter) {
5174                    this.scribe.space();
5175                }
5176            }
5177            bounds[boundsLength - 1].traverse(this, scope);
5178        }
5179        return false;
5180    }
5181    public boolean visit(TypeParameter typeParameter, ClassScope scope) {
5182        this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier);
5183        if (typeParameter.type != null) {
5184            this.scribe.space();
5185            this.scribe.printNextToken(TerminalTokens.TokenNameextends, true);
5186            this.scribe.space();
5187            typeParameter.type.traverse(this, scope);
5188        }
5189        final TypeReference[] bounds = typeParameter.bounds;
5190        if (bounds != null) {
5191            this.scribe.printNextToken(TerminalTokens.TokenNameAND, this.preferences.insert_space_before_and_in_type_parameter);
5192            if (this.preferences.insert_space_after_and_in_type_parameter) {
5193                this.scribe.space();
5194            }
5195            int boundsLength = bounds.length;
5196            for (int i = 0; i < boundsLength - 1; i++) {
5197                bounds[i].traverse(this, scope);
5198                this.scribe.printNextToken(TerminalTokens.TokenNameAND, this.preferences.insert_space_before_and_in_type_parameter);
5199                if (this.preferences.insert_space_after_and_in_type_parameter) {
5200                    this.scribe.space();
5201                }
5202            }
5203            bounds[boundsLength - 1].traverse(this, scope);
5204        }
5205        return false;
5206    }
5207
5208    /**
5209     * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.UnaryExpression, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
5210     */

5211    public boolean visit(UnaryExpression unaryExpression, BlockScope scope) {
5212
5213        final int numberOfParens = (unaryExpression.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
5214        if (numberOfParens > 0) {
5215            manageOpeningParenthesizedExpression(unaryExpression, numberOfParens);
5216        }
5217
5218        /*
5219         * Print the operator
5220         */

5221        int operator;
5222        int operatorValue = (unaryExpression.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT;
5223        switch(operatorValue) {
5224            case OperatorIds.PLUS:
5225                operator = TerminalTokens.TokenNamePLUS;
5226                break;
5227            case OperatorIds.MINUS:
5228                operator = TerminalTokens.TokenNameMINUS;
5229                break;
5230            case OperatorIds.TWIDDLE:
5231                operator = TerminalTokens.TokenNameTWIDDLE;
5232                break;
5233            default:
5234                operator = TerminalTokens.TokenNameNOT;
5235        }
5236
5237        this.scribe.printNextToken(operator, this.preferences.insert_space_before_unary_operator);
5238        if (this.preferences.insert_space_after_unary_operator) {
5239            this.scribe.space();
5240        }
5241        Expression expression = unaryExpression.expression;
5242
5243        if (expression instanceof PrefixExpression) {
5244            PrefixExpression prefixExpression = (PrefixExpression) expression;
5245            final int numberOfParensForExpression = (prefixExpression.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
5246            if (numberOfParensForExpression == 0) {
5247                switch(operatorValue) {
5248                    case OperatorIds.PLUS:
5249                        if (prefixExpression.operator == OperatorIds.PLUS) {
5250                            this.scribe.space();
5251                        }
5252                        break;
5253                    case OperatorIds.MINUS:
5254                        if (prefixExpression.operator == OperatorIds.MINUS) {
5255                            this.scribe.space();
5256                        }
5257                        break;
5258                }
5259            }
5260            expression.traverse(this, scope);
5261        } else {
5262            expression.traverse(this, scope);
5263        }
5264
5265        if (numberOfParens > 0) {
5266            manageClosingParenthesizedExpression(unaryExpression, numberOfParens);
5267        }
5268        return false;
5269    }
5270
5271    /**
5272     * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.WhileStatement, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
5273     */

5274    public boolean visit(WhileStatement whileStatement, BlockScope scope) {
5275
5276        this.scribe.printNextToken(TerminalTokens.TokenNamewhile);
5277        final int line = this.scribe.line;
5278        this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_while);
5279        
5280        if (this.preferences.insert_space_after_opening_paren_in_while) {
5281            this.scribe.space();
5282        }
5283        whileStatement.condition.traverse(this, scope);
5284        
5285        this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_while);
5286        
5287        final Statement action = whileStatement.action;
5288        if (action != null) {
5289            if (action instanceof Block) {
5290                formatLeftCurlyBrace(line, this.preferences.brace_position_for_block);
5291                action.traverse(this, scope);
5292            } else if (action instanceof EmptyStatement) {
5293                /*
5294                 * This is an empty statement
5295                 */

5296                formatNecessaryEmptyStatement();
5297            } else {
5298                this.scribe.printNewLine();
5299                this.scribe.indent();
5300                action.traverse(this, scope);
5301                if (action instanceof Expression) {
5302                    this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
5303                    this.scribe.printTrailingComment();
5304                }
5305                this.scribe.unIndent();
5306            }
5307        } else {
5308            /*
5309             * This is an empty statement
5310             */

5311            formatNecessaryEmptyStatement();
5312        }
5313        return false;
5314    }
5315    public boolean visit(Wildcard wildcard, BlockScope scope) {
5316        this.scribe.printNextToken(TerminalTokens.TokenNameQUESTION, this.preferences.insert_space_before_question_in_wilcard);
5317        switch(wildcard.kind) {
5318            case Wildcard.SUPER :
5319                this.scribe.printNextToken(TerminalTokens.TokenNamesuper, true);
5320                this.scribe.space();
5321                wildcard.bound.traverse(this, scope);
5322                break;
5323            case Wildcard.EXTENDS :
5324                this.scribe.printNextToken(TerminalTokens.TokenNameextends, true);
5325                this.scribe.space();
5326                wildcard.bound.traverse(this, scope);
5327                break;
5328            case Wildcard.UNBOUND :
5329                if (this.preferences.insert_space_after_question_in_wilcard) {
5330                    this.scribe.space();
5331                }
5332        }
5333        return false;
5334    }
5335    public boolean visit(Wildcard wildcard, ClassScope scope) {
5336        this.scribe.printNextToken(TerminalTokens.TokenNameQUESTION, this.preferences.insert_space_before_question_in_wilcard);
5337        switch(wildcard.kind) {
5338            case Wildcard.SUPER :
5339                this.scribe.printNextToken(TerminalTokens.TokenNamesuper, true);
5340                this.scribe.space();
5341                wildcard.bound.traverse(this, scope);
5342                break;
5343            case Wildcard.EXTENDS :
5344                this.scribe.printNextToken(TerminalTokens.TokenNameextends, true);
5345                this.scribe.space();
5346                wildcard.bound.traverse(this, scope);
5347                break;
5348            case Wildcard.UNBOUND :
5349                if (this.preferences.insert_space_after_question_in_wilcard) {
5350                    this.scribe.space();
5351                }
5352        }
5353        return false;
5354    }
5355}
5356
Popular Tags