Package org.aspectj.org.eclipse.jdt.internal.formatter

Source Code of org.aspectj.org.eclipse.jdt.internal.formatter.CodeFormatterVisitor

/*******************************************************************************
* Copyright (c) 2002, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*     IBM Corporation - initial API and implementation
*******************************************************************************/
package org.aspectj.org.eclipse.jdt.internal.formatter;

import java.util.ArrayList;
import java.util.Map;

import org.aspectj.org.eclipse.jdt.core.JavaCore;
import org.aspectj.org.eclipse.jdt.core.compiler.IProblem;
import org.aspectj.org.eclipse.jdt.core.compiler.InvalidInputException;
import org.aspectj.org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants;
import org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.AND_AND_Expression;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.AllocationExpression;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.AnnotationMethodDeclaration;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Argument;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ArrayAllocationExpression;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ArrayInitializer;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ArrayQualifiedTypeReference;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ArrayReference;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ArrayTypeReference;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.AssertStatement;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Assignment;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.BinaryExpression;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Block;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.BreakStatement;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.CaseStatement;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.CastExpression;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.CharLiteral;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ClassLiteralAccess;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Clinit;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.CombinedBinaryExpression;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.CompoundAssignment;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ConditionalExpression;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ContinueStatement;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.DoStatement;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.DoubleLiteral;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.EmptyStatement;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.EqualExpression;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Expression;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.FalseLiteral;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.FieldReference;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.FloatLiteral;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ForStatement;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ForeachStatement;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.IfStatement;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ImportReference;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Initializer;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.InstanceOfExpression;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.IntLiteral;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.LabeledStatement;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.LongLiteral;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.MarkerAnnotation;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.MemberValuePair;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.MessageSend;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.NormalAnnotation;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ParameterizedQualifiedTypeReference;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ParameterizedSingleTypeReference;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.SingleMemberAnnotation;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.StringLiteralConcatenation;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.NullLiteral;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.OR_OR_Expression;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.OperatorIds;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.PostfixExpression;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.PrefixExpression;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.QualifiedAllocationExpression;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.QualifiedSuperReference;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.QualifiedThisReference;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ReturnStatement;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.SingleTypeReference;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Statement;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.StringLiteral;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.SuperReference;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.SwitchStatement;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.SynchronizedStatement;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ThisReference;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ThrowStatement;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TrueLiteral;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TryStatement;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeParameter;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.UnaryExpression;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.WhileStatement;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Wildcard;
import org.aspectj.org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.aspectj.org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.aspectj.org.eclipse.jdt.internal.compiler.impl.Constant;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ClassScope;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.MethodScope;
import org.aspectj.org.eclipse.jdt.internal.compiler.parser.Scanner;
import org.aspectj.org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
import org.aspectj.org.eclipse.jdt.internal.core.util.CodeSnippetParsingUtil;
import org.aspectj.org.eclipse.jdt.internal.formatter.align.Alignment;
import org.aspectj.org.eclipse.jdt.internal.formatter.align.AlignmentException;
import org.aspectj.org.eclipse.jdt.internal.formatter.comment.CommentRegion;
import org.eclipse.text.edits.TextEdit;

/**
* This class is responsible for formatting a valid java source code.
* @since 2.1
*/
/*
   <extension
         id="org.aspectj.org.eclipse.jdt.core.newformatter.codeformatter"
         name="org.aspectj.org.eclipse.jdt.core.newformatter.codeformatter"
         point="org.aspectj.org.eclipse.jdt.core.codeFormatter">
      <codeFormatter
            class="org.aspectj.org.eclipse.jdt.internal.formatter.CodeFormatterVisitor">
      </codeFormatter>
   </extension>
*/
public class CodeFormatterVisitor extends ASTVisitor {

  public static class MultiFieldDeclaration extends FieldDeclaration {
   
    FieldDeclaration[] declarations;
   
    MultiFieldDeclaration(FieldDeclaration[] declarations){
      this.declarations = declarations;
      this.modifiers = declarations[0].modifiers;
    }
  }
 
  public final static boolean DEBUG = false;
  private static final int NO_MODIFIERS = 0;
  /*
   * Set of expected tokens type for a single type reference.
   * This array needs to be SORTED.
   */
  private static final int[] SINGLETYPEREFERENCE_EXPECTEDTOKENS = new int[] {
    TerminalTokens.TokenNameIdentifier,
    TerminalTokens.TokenNameboolean,
    TerminalTokens.TokenNamebyte,
    TerminalTokens.TokenNamechar,
    TerminalTokens.TokenNamedouble,
    TerminalTokens.TokenNamefloat,
    TerminalTokens.TokenNameint,
    TerminalTokens.TokenNamelong,
    TerminalTokens.TokenNameshort,
    TerminalTokens.TokenNamevoid
  };
  private static final int[] CLOSING_GENERICS_EXPECTEDTOKENS = new int[] {
    TerminalTokens.TokenNameRIGHT_SHIFT,
    TerminalTokens.TokenNameUNSIGNED_RIGHT_SHIFT,
    TerminalTokens.TokenNameGREATER
  };
  private int chunkKind;
  public int lastLocalDeclarationSourceStart;
  private Scanner localScanner;
  public DefaultCodeFormatterOptions preferences;
  public Scribe scribe;

  public CodeFormatterVisitor(DefaultCodeFormatterOptions preferences, Map settings, int offset, int length, CodeSnippetParsingUtil codeSnippetParsingUtil) {
    long sourceLevel = settings == null
      ? ClassFileConstants.JDK1_3
      : CompilerOptions.versionToJdkLevel(settings.get(JavaCore.COMPILER_SOURCE));
    this.localScanner = new Scanner(true, false, false/*nls*/, sourceLevel/*sourceLevel*/, null/*taskTags*/, null/*taskPriorities*/, true/*taskCaseSensitive*/);
   
    this.preferences = preferences;
    this.scribe = new Scribe(this, sourceLevel, offset, length, codeSnippetParsingUtil);
  }
 
  /**
   * @see org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor#acceptProblem(org.aspectj.org.eclipse.jdt.core.compiler.IProblem)
   */
  public void acceptProblem(IProblem problem) {
    super.acceptProblem(problem);
  }

  private BinaryExpressionFragmentBuilder buildFragments(BinaryExpression binaryExpression, BlockScope scope) {
    BinaryExpressionFragmentBuilder builder = new BinaryExpressionFragmentBuilder();

    if (binaryExpression instanceof CombinedBinaryExpression) {
      binaryExpression.traverse(builder, scope);
      return builder;
    }
    switch((binaryExpression.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT) {
      case OperatorIds.MULTIPLY :
        binaryExpression.left.traverse(builder, scope);
        builder.operatorsList.add(new Integer(TerminalTokens.TokenNameMULTIPLY));
        binaryExpression.right.traverse(builder, scope);
        break;
      case OperatorIds.PLUS :
        binaryExpression.left.traverse(builder, scope);
        builder.operatorsList.add(new Integer(TerminalTokens.TokenNamePLUS));
        binaryExpression.right.traverse(builder, scope);
        break;
      case OperatorIds.DIVIDE :
        binaryExpression.left.traverse(builder, scope);
        builder.operatorsList.add(new Integer(TerminalTokens.TokenNameDIVIDE));
        binaryExpression.right.traverse(builder, scope);
        break;
      case OperatorIds.REMAINDER :
        binaryExpression.left.traverse(builder, scope);
        builder.operatorsList.add(new Integer(TerminalTokens.TokenNameREMAINDER));
        binaryExpression.right.traverse(builder, scope);
        break;
      case OperatorIds.XOR :
        binaryExpression.left.traverse(builder, scope);
        builder.operatorsList.add(new Integer(TerminalTokens.TokenNameXOR));
        binaryExpression.right.traverse(builder, scope);
        break;
      case OperatorIds.MINUS :
        binaryExpression.left.traverse(builder, scope);
        builder.operatorsList.add(new Integer(TerminalTokens.TokenNameMINUS));
        binaryExpression.right.traverse(builder, scope);
        break;
      case OperatorIds.OR :
        binaryExpression.left.traverse(builder, scope);
        builder.operatorsList.add(new Integer(TerminalTokens.TokenNameOR));
        binaryExpression.right.traverse(builder, scope);
        break;
      case OperatorIds.AND :
        binaryExpression.left.traverse(builder, scope);
        builder.operatorsList.add(new Integer(TerminalTokens.TokenNameAND));
        binaryExpression.right.traverse(builder, scope);
        break;
      case OperatorIds.AND_AND :
        binaryExpression.left.traverse(builder, scope);
        builder.operatorsList.add(new Integer(TerminalTokens.TokenNameAND_AND));
        binaryExpression.right.traverse(builder, scope);
        break;
      case OperatorIds.OR_OR :
        binaryExpression.left.traverse(builder, scope);
        builder.operatorsList.add(new Integer(TerminalTokens.TokenNameOR_OR));
        binaryExpression.right.traverse(builder, scope);
        break;
    }

    return builder;
  }

  private CascadingMethodInvocationFragmentBuilder buildFragments(MessageSend messageSend, BlockScope scope) {
    CascadingMethodInvocationFragmentBuilder builder = new CascadingMethodInvocationFragmentBuilder();

    messageSend.traverse(builder, scope);
    return builder;
 
  public boolean checkChunkStart(int kind) {
    if (this.chunkKind != kind) {
      this.chunkKind = kind;
      return true;
    }
    return false;
  }
 
  private boolean commentStartsBlock(int start, int end) {
    this.localScanner.resetTo(start, end);
    try {
      if (this.localScanner.getNextToken() ==  TerminalTokens.TokenNameLBRACE) {
        switch(this.localScanner.getNextToken()) {
          case TerminalTokens.TokenNameCOMMENT_BLOCK :
          case TerminalTokens.TokenNameCOMMENT_JAVADOC :
          case TerminalTokens.TokenNameCOMMENT_LINE :
            return true;
        }
      }
    } catch(InvalidInputException e) {
      // ignore
    }
    return false;
  }

  private ASTNode[] computeMergedMemberDeclarations(ASTNode[] nodes){
    ArrayList mergedNodes = new ArrayList();
    for (int i = 0, max = nodes.length; i < max; i++) {
      ASTNode currentNode = nodes[i];
      if (currentNode instanceof FieldDeclaration) {
        FieldDeclaration currentField = (FieldDeclaration) currentNode;
        if (mergedNodes.size() == 0) {
          // first node
          mergedNodes.add(currentNode);
        } else {
          // we need to check if the previous merged node is a field declaration
          ASTNode previousMergedNode = (ASTNode) mergedNodes.get(mergedNodes.size() - 1);
          if (previousMergedNode instanceof MultiFieldDeclaration) {
            // we merge the current node
            MultiFieldDeclaration multiFieldDeclaration = (MultiFieldDeclaration) previousMergedNode;
            int length = multiFieldDeclaration.declarations.length;
            System.arraycopy(multiFieldDeclaration.declarations, 0, multiFieldDeclaration.declarations= new FieldDeclaration[length+1], 0, length);
            multiFieldDeclaration.declarations[length] = currentField;
          } else if (previousMergedNode instanceof FieldDeclaration) {
            // need to check we need to create a multiple field declaration
            final FieldDeclaration previousFieldDeclaration = (FieldDeclaration)previousMergedNode;
            if (currentField.declarationSourceStart == previousFieldDeclaration.declarationSourceStart) {
              // we create a multi field declaration
              final MultiFieldDeclaration multiFieldDeclaration = new MultiFieldDeclaration(new FieldDeclaration[]{ previousFieldDeclaration, currentField});
              multiFieldDeclaration.annotations = previousFieldDeclaration.annotations;
              mergedNodes.set(mergedNodes.size() - 1, multiFieldDeclaration);
            } else {
              mergedNodes.add(currentNode);
            }
          } else {
            mergedNodes.add(currentNode);
          }
        }
      } else {
        mergedNodes.add(currentNode);
      }
    }
    if (mergedNodes.size() != nodes.length) {
      ASTNode[] result = new ASTNode[mergedNodes.size()];
      mergedNodes.toArray(result);
      return result;
    } else {
      return nodes;
    }
  }
 
  private ASTNode[] computeMergedMemberDeclarations(TypeDeclaration typeDeclaration){
   
    int fieldIndex = 0, fieldCount = (typeDeclaration.fields == null) ? 0 : typeDeclaration.fields.length;
    FieldDeclaration field = fieldCount == 0 ? null : typeDeclaration.fields[fieldIndex];
    int fieldStart = field == null ? Integer.MAX_VALUE : field.declarationSourceStart;

    int methodIndex = 0, methodCount = (typeDeclaration.methods == null) ? 0 : typeDeclaration.methods.length;
    AbstractMethodDeclaration method = methodCount == 0 ? null : typeDeclaration.methods[methodIndex];
    int methodStart = method == null ? Integer.MAX_VALUE : method.declarationSourceStart;

    int typeIndex = 0, typeCount = (typeDeclaration.memberTypes == null) ? 0 : typeDeclaration.memberTypes.length;
    TypeDeclaration type = typeCount == 0 ? null : typeDeclaration.memberTypes[typeIndex];
    int typeStart = type == null ? Integer.MAX_VALUE : type.declarationSourceStart;
 
    final int memberLength = fieldCount+methodCount+typeCount;
    ASTNode[] members = new ASTNode[memberLength];
    if (memberLength != 0) {
      int index = 0;
      int previousFieldStart = -1;
      do {
        if (fieldStart < methodStart && fieldStart < typeStart) {
          if (field.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT) {
            // filter out enum constants
            previousFieldStart = fieldStart;
            if (++fieldIndex < fieldCount) { // find next field if any
              fieldStart = (field = typeDeclaration.fields[fieldIndex]).declarationSourceStart;
            } else {
              fieldStart = Integer.MAX_VALUE;
            }
            continue;
          }
          // next member is a field
          if (fieldStart == previousFieldStart){
            ASTNode previousMember = members[index - 1];
            if (previousMember instanceof MultiFieldDeclaration) {
              MultiFieldDeclaration multiField = (MultiFieldDeclaration) previousMember;
              int length = multiField.declarations.length;
              System.arraycopy(multiField.declarations, 0, multiField.declarations=new FieldDeclaration[length+1], 0, length);
              multiField.declarations[length] = field;
            } else {
              FieldDeclaration fieldDeclaration = (FieldDeclaration)previousMember;
              final MultiFieldDeclaration multiFieldDeclaration = new MultiFieldDeclaration(new FieldDeclaration[]{ fieldDeclaration, field});
              multiFieldDeclaration.annotations = fieldDeclaration.annotations;
              members[index - 1] = multiFieldDeclaration;
            }
          } else {
            members[index++] = field;
          }
          previousFieldStart = fieldStart;
          if (++fieldIndex < fieldCount) { // find next field if any
            fieldStart = (field = typeDeclaration.fields[fieldIndex]).declarationSourceStart;
          } else {
            fieldStart = Integer.MAX_VALUE;
          }
        } else if (methodStart < fieldStart && methodStart < typeStart) {
          // next member is a method
          if (!method.isDefaultConstructor() && !method.isClinit()) {
            members[index++] = method;         
          }
          if (++methodIndex < methodCount) { // find next method if any
            methodStart = (method = typeDeclaration.methods[methodIndex]).declarationSourceStart;
          } else {
            methodStart = Integer.MAX_VALUE;
          }
        } else {
          // next member is a type
          members[index++] = type;
          if (++typeIndex < typeCount) { // find next type if any
            typeStart = (type = typeDeclaration.memberTypes[typeIndex]).declarationSourceStart;
          } else {
            typeStart = Integer.MAX_VALUE;
          }
        }
      } while ((fieldIndex < fieldCount) || (typeIndex < typeCount) || (methodIndex < methodCount));
     
      if (members.length != index) {
        System.arraycopy(members, 0, members=new ASTNode[index], 0, index);
      }
    }
    return members;
  }
 
  private boolean dumpBinaryExpression(
    BinaryExpression binaryExpression,
    int operator,
    BlockScope scope) {

    final int numberOfParens = (binaryExpression.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;

    if (numberOfParens > 0) {
      manageOpeningParenthesizedExpression(binaryExpression, numberOfParens);
   
    BinaryExpressionFragmentBuilder builder = buildFragments(binaryExpression, scope);
    final int fragmentsSize = builder.size();
   
    if ((builder.realFragmentsSize() > 1 || builder.size() > 4) && numberOfParens == 0) {
      this.scribe.printComment();
      Alignment binaryExpressionAlignment = this.scribe.createAlignment("binaryExpressionAlignment", this.preferences.alignment_for_binary_expression, Alignment.R_OUTERMOST, fragmentsSize, this.scribe.scanner.currentPosition); //$NON-NLS-1$
      this.scribe.enterAlignment(binaryExpressionAlignment);
      boolean ok = false;
      ASTNode[] fragments = builder.fragments();
      int[] operators = builder.operators();
      do {
        try {
          for (int i = 0; i < fragmentsSize - 1; i++) {
            ASTNode fragment = fragments[i];
            fragment.traverse(this, scope);
            this.scribe.printTrailingComment();
            if (this.scribe.lastNumberOfNewLines == 1) {
              // a new line has been inserted by printTrailingComment()
              this.scribe.indentationLevel = binaryExpressionAlignment.breakIndentationLevel;
            }
            if (this.preferences.wrap_before_binary_operator) {
              this.scribe.alignFragment(binaryExpressionAlignment, i);
              this.scribe.printNextToken(operators[i], this.preferences.insert_space_before_binary_operator);
            } else {
              this.scribe.printNextToken(operators[i], this.preferences.insert_space_before_binary_operator);
              this.scribe.alignFragment(binaryExpressionAlignment, i);
            }
            if (operators[i] == TerminalTokens.TokenNameMINUS && isNextToken(TerminalTokens.TokenNameMINUS)) {
              // the next character is a minus (unary operator)
              this.scribe.space();
            }
            if (this.preferences.insert_space_after_binary_operator) {
              this.scribe.space();
            }
          }
          fragments[fragmentsSize - 1].traverse(this, scope);
          this.scribe.printTrailingComment();
          ok = true;
        } catch(AlignmentException e){
          this.scribe.redoAlignment(e);
        }
      } while (!ok);   
      this.scribe.exitAlignment(binaryExpressionAlignment, true);
    } else {
      binaryExpression.left.traverse(this, scope);
      this.scribe.printNextToken(operator, this.preferences.insert_space_before_binary_operator);
      if (operator == TerminalTokens.TokenNameMINUS && isNextToken(TerminalTokens.TokenNameMINUS)) {
        // the next character is a minus (unary operator)
        this.scribe.space();
      }
      if (this.preferences.insert_space_after_binary_operator) {
        this.scribe.space();
      }
      binaryExpression.right.traverse(this, scope);
   
    if (numberOfParens > 0) {
      manageClosingParenthesizedExpression(binaryExpression, numberOfParens);
    }
    return false;
  }

  private boolean dumpEqualityExpression(
    BinaryExpression binaryExpression,
    int operator,
    BlockScope scope) {
 
    final int numberOfParens = (binaryExpression.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
 
    if (numberOfParens > 0) {
      manageOpeningParenthesizedExpression(binaryExpression, numberOfParens);
   
    binaryExpression.left.traverse(this, scope);
    this.scribe.printNextToken(operator, this.preferences.insert_space_before_binary_operator);
    if (this.preferences.insert_space_after_binary_operator) {
      this.scribe.space();
    }
    binaryExpression.right.traverse(this, scope);

    if (numberOfParens > 0) {
      manageClosingParenthesizedExpression(binaryExpression, numberOfParens);
    }
    return false;
  }

  private final TextEdit failedToFormat() {
    if (DEBUG) {
      System.out.println("COULD NOT FORMAT \n" + this.scribe.scanner); //$NON-NLS-1$
      System.out.println(this.scribe);
    }
    return null;
  }

  private void format(
    AbstractMethodDeclaration methodDeclaration,
    ClassScope scope,
    boolean isChunkStart,
    boolean isFirstClassBodyDeclaration) {

    if (isFirstClassBodyDeclaration) {
      int newLinesBeforeFirstClassBodyDeclaration = this.preferences.blank_lines_before_first_class_body_declaration;
      if (newLinesBeforeFirstClassBodyDeclaration > 0) {
        this.scribe.printEmptyLines(newLinesBeforeFirstClassBodyDeclaration);
      }
    } else {
      final int newLineBeforeChunk = isChunkStart ? this.preferences.blank_lines_before_new_chunk : 0;
      if (newLineBeforeChunk > 0) {
        this.scribe.printEmptyLines(newLineBeforeChunk);
      }
    }
    final int newLinesBeforeMethod = this.preferences.blank_lines_before_method;
    if (newLinesBeforeMethod > 0 && !isFirstClassBodyDeclaration) {
      this.scribe.printEmptyLines(newLinesBeforeMethod);
    } else if (this.scribe.line != 0 || this.scribe.column != 1) {
      this.scribe.printNewLine();
    }
    methodDeclaration.traverse(this, scope);
  }

  private void format(FieldDeclaration fieldDeclaration, ASTVisitor visitor, MethodScope scope, boolean isChunkStart, boolean isFirstClassBodyDeclaration) {
   
    if (isFirstClassBodyDeclaration) {
      int newLinesBeforeFirstClassBodyDeclaration = this.preferences.blank_lines_before_first_class_body_declaration;
      if (newLinesBeforeFirstClassBodyDeclaration > 0) {
        this.scribe.printEmptyLines(newLinesBeforeFirstClassBodyDeclaration);
      }
    } else {
      int newLineBeforeChunk = isChunkStart ? this.preferences.blank_lines_before_new_chunk : 0;
      if (newLineBeforeChunk > 0) {
        this.scribe.printEmptyLines(newLineBeforeChunk);
      }
      final int newLinesBeforeField = this.preferences.blank_lines_before_field;
      if (newLinesBeforeField > 0) {
        this.scribe.printEmptyLines(newLinesBeforeField);
      }
    }
    Alignment memberAlignment = this.scribe.getMemberAlignment();
 
        this.scribe.printComment();
    this.scribe.printModifiers(fieldDeclaration.annotations, this);
    this.scribe.space();
    /*
     * Field type
     */
    fieldDeclaration.type.traverse(this, scope);
   
    /*
     * Field name
     */
    this.scribe.alignFragment(memberAlignment, 0);
 
    this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, true);
 
    /*
     * Check for extra dimensions
     */
    int extraDimensions = getDimensions();
    if (extraDimensions != 0) {
       for (int i = 0; i < extraDimensions; i++) {
         this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET);
         this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET);
       }
    }
 
    /*
     * Field initialization
     */
    final Expression initialization = fieldDeclaration.initialization;
    if (initialization != null) {
      this.scribe.alignFragment(memberAlignment, 1);
      this.scribe.printNextToken(TerminalTokens.TokenNameEQUAL, this.preferences.insert_space_before_assignment_operator);
      if (this.preferences.insert_space_after_assignment_operator) {
        this.scribe.space();
      }
      Alignment assignmentAlignment = this.scribe.createAlignment("fieldDeclarationAssignmentAlignment", this.preferences.alignment_for_assignment, Alignment.R_OUTERMOST, 1, this.scribe.scanner.currentPosition); //$NON-NLS-1$
      this.scribe.enterAlignment(assignmentAlignment);
      boolean ok = false;
      do {
        try {
          this.scribe.alignFragment(assignmentAlignment, 0);
          initialization.traverse(this, scope);
          ok = true;
        } catch(AlignmentException e){
          this.scribe.redoAlignment(e);
        }
      } while (!ok);   
      this.scribe.exitAlignment(assignmentAlignment, true);     
    }
   
    this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);

    if (memberAlignment != null) {
      this.scribe.alignFragment(memberAlignment, 2);
      this.scribe.printTrailingComment();
    } else {
      this.scribe.space();
      this.scribe.printTrailingComment();
    }
  }
 
  private void format(ImportReference importRef, boolean isLast) {
    this.scribe.printNextToken(TerminalTokens.TokenNameimport);
    this.preferences.number_of_empty_lines_to_preserve = this.preferences.blank_lines_between_import_groups;
    this.scribe.space();
    if (importRef.isStatic()) {
      this.scribe.printNextToken(TerminalTokens.TokenNamestatic);
      this.scribe.space();
    }
    if ((importRef.bits & ASTNode.OnDemand) != 0) {
      this.scribe.printQualifiedReference(importRef.sourceEnd);
      this.scribe.printNextToken(TerminalTokens.TokenNameDOT);
      this.scribe.printNextToken(TerminalTokens.TokenNameMULTIPLY);     
      this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
    } else {
      this.scribe.printQualifiedReference(importRef.sourceEnd);
      this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
    }
    if (isLast) {
      this.scribe.printTrailingComment();
    } else {
      this.scribe.printTrailingComment(this.preferences.blank_lines_between_import_groups);
    }
    this.scribe.printNewLine();     
  }


  private void format(MultiFieldDeclaration multiFieldDeclaration, ASTVisitor visitor, MethodScope scope, boolean isChunkStart, boolean isFirstClassBodyDeclaration) {
 
    if (isFirstClassBodyDeclaration) {
      int newLinesBeforeFirstClassBodyDeclaration = this.preferences.blank_lines_before_first_class_body_declaration;
      if (newLinesBeforeFirstClassBodyDeclaration > 0) {
        this.scribe.printEmptyLines(newLinesBeforeFirstClassBodyDeclaration);
      }
    } else {
      int newLineBeforeChunk = isChunkStart ? this.preferences.blank_lines_before_new_chunk : 0;
      if (newLineBeforeChunk > 0) {
        this.scribe.printEmptyLines(newLineBeforeChunk);
      }
      final int newLinesBeforeField = this.preferences.blank_lines_before_field;
      if (newLinesBeforeField > 0) {
        this.scribe.printEmptyLines(newLinesBeforeField);
      }
    }
    Alignment fieldAlignment = this.scribe.getMemberAlignment();
 
        this.scribe.printComment();
    this.scribe.printModifiers(multiFieldDeclaration.annotations, this);
    this.scribe.space();
 
    multiFieldDeclaration.declarations[0].type.traverse(this, scope);
 
    final int multipleFieldDeclarationsLength = multiFieldDeclaration.declarations.length;

    Alignment multiFieldDeclarationsAlignment =this.scribe.createAlignment(
        "multiple_field",//$NON-NLS-1$
        this.preferences.alignment_for_multiple_fields,
        multipleFieldDeclarationsLength - 1,
        this.scribe.scanner.currentPosition);
    this.scribe.enterAlignment(multiFieldDeclarationsAlignment);
 
    boolean ok = false;
    do {
      try {
        for (int i = 0, length = multipleFieldDeclarationsLength; i < length; i++) {
          FieldDeclaration fieldDeclaration = multiFieldDeclaration.declarations[i];
          /*
           * Field name
           */
          if (i == 0) {
            this.scribe.alignFragment(fieldAlignment, 0);
            this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, true);
          } else {
            this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, false);
          }
     
          /*
           * Check for extra dimensions
           */
          int extraDimensions = getDimensions();
          if (extraDimensions != 0) {
             for (int index = 0; index < extraDimensions; index++) {
               this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET);
               this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET);
             }
          }
       
          /*
           * Field initialization
           */
          final Expression initialization = fieldDeclaration.initialization;
          if (initialization != null) {
            if (i == 0) {
              this.scribe.alignFragment(fieldAlignment, 1);
            }
            this.scribe.printNextToken(TerminalTokens.TokenNameEQUAL, this.preferences.insert_space_before_assignment_operator);
            if (this.preferences.insert_space_after_assignment_operator) {
              this.scribe.space();
            }
            initialization.traverse(this, scope);
          }
         
          if (i != length - 1) {
            this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_multiple_field_declarations);
            this.scribe.printTrailingComment();
            this.scribe.alignFragment(multiFieldDeclarationsAlignment, i);

            if (this.preferences.insert_space_after_comma_in_multiple_field_declarations) {
              this.scribe.space();
            }
          } else {
            this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
            this.scribe.alignFragment(fieldAlignment, 2);
            this.scribe.printTrailingComment();
          }
        }
        ok = true;
      } catch (AlignmentException e) {
        this.scribe.redoAlignment(e);
      }
    } while (!ok);
    this.scribe.exitAlignment(multiFieldDeclarationsAlignment, true);       
  }
 
  /**
   * @see org.aspectj.org.eclipse.jdt.core.formatter.CodeFormatter#format(int, String, int, int, int, String)
   */
  public TextEdit format(String string, ASTNode[] nodes) {
    // reset the scribe
    this.scribe.reset();
   
    long startTime = System.currentTimeMillis();

    final char[] compilationUnitSource = string.toCharArray();
   
    this.localScanner.setSource(compilationUnitSource);
    this.scribe.initializeScanner(compilationUnitSource);

    if (nodes == null) {
      return null;
    }

    this.lastLocalDeclarationSourceStart = -1;
    try {
      formatClassBodyDeclarations(nodes);
    } catch(AbortFormatting e){
      return failedToFormat();
    }
    if (DEBUG){
      System.out.println("Formatting time: " + (System.currentTimeMillis() - startTime))//$NON-NLS-1$
    }
    return this.scribe.getRootEdit();
  }

  /**
   * @see org.aspectj.org.eclipse.jdt.core.formatter.CodeFormatter#format(int, String, int, int, int, String)
   */
  public TextEdit format(String string, CompilationUnitDeclaration compilationUnitDeclaration) {
    // reset the scribe
    this.scribe.reset();
   
    if (compilationUnitDeclaration == null || compilationUnitDeclaration.ignoreFurtherInvestigation) {
      return failedToFormat();
    }

    long startTime = System.currentTimeMillis();

    final char[] compilationUnitSource = string.toCharArray();
   
    this.localScanner.setSource(compilationUnitSource);
    this.scribe.initializeScanner(compilationUnitSource);

    this.lastLocalDeclarationSourceStart = -1;
    try {
      compilationUnitDeclaration.traverse(this, compilationUnitDeclaration.scope);
    } catch(AbortFormatting e){
      return failedToFormat();
    }
    if (DEBUG){
      System.out.println("Formatting time: " + (System.currentTimeMillis() - startTime))//$NON-NLS-1$
    }
    return this.scribe.getRootEdit();
  }

  /**
   * @see org.aspectj.org.eclipse.jdt.core.formatter.CodeFormatter#format(int, String, int, int, int, String)
   */
  public TextEdit format(String string, ConstructorDeclaration constructorDeclaration) {
    // reset the scribe
    this.scribe.reset();
   
    long startTime = System.currentTimeMillis();

    final char[] compilationUnitSource = string.toCharArray();
   
    this.localScanner.setSource(compilationUnitSource);
    this.scribe.initializeScanner(compilationUnitSource);

    if (constructorDeclaration == null) {
      return null;
    }

    this.lastLocalDeclarationSourceStart = -1;
    try {
      ExplicitConstructorCall explicitConstructorCall = constructorDeclaration.constructorCall;
      if (explicitConstructorCall != null && !explicitConstructorCall.isImplicitSuper()) {
        explicitConstructorCall.traverse(this, null);
      }
      Statement[] statements = constructorDeclaration.statements;
      if (statements != null) {
        formatStatements(null, statements, false);
      }
      if (hasComments()) {
        this.scribe.printNewLine();
      }
      this.scribe.printComment();
    } catch(AbortFormatting e){
      return failedToFormat();
    }
    if (DEBUG){
      System.out.println("Formatting time: " + (System.currentTimeMillis() - startTime))//$NON-NLS-1$
    }
    return this.scribe.getRootEdit();
  }

  /**
   * @see org.aspectj.org.eclipse.jdt.core.formatter.CodeFormatter#format(int, String, int, int, int, String)
   */
  public TextEdit format(String string, Expression expression) {
    // reset the scribe
    this.scribe.reset();
   
    long startTime = System.currentTimeMillis();

    final char[] compilationUnitSource = string.toCharArray();
   
    this.localScanner.setSource(compilationUnitSource);
    this.scribe.initializeScanner(compilationUnitSource);

    if (expression == null) {
      return null;
    }

    this.lastLocalDeclarationSourceStart = -1;
    try {
      expression.traverse(this, (BlockScope) null);
      this.scribe.printComment();
    } catch(AbortFormatting e){
      return failedToFormat();
    }
    if (DEBUG){
      System.out.println("Formatting time: " + (System.currentTimeMillis() - startTime))//$NON-NLS-1$
    }
    return this.scribe.getRootEdit();
  }
 
  /**
   * @see org.aspectj.org.eclipse.jdt.core.formatter.CodeFormatter#format(int, String, int, int, int, String)
   */
  public TextEdit format(String string, CommentRegion region) {
    // reset the scribe
    this.scribe.reset();
   
    if (region == null) {
      return failedToFormat();
    }

    long startTime = 0;
    if (DEBUG){
      startTime = System.currentTimeMillis();
    }

    final char[] compilationUnitSource = string.toCharArray();
   
    this.scribe.initializeScanner(compilationUnitSource);

    TextEdit result = null;
    try {
      result = region.format(this.preferences.initial_indentation_level, true);
    } catch(AbortFormatting e){
      return failedToFormat();
    }
    if (DEBUG){
      System.out.println("Formatting time: " + (System.currentTimeMillis() - startTime))//$NON-NLS-1$
    }
    return result;
  }

  private void format(TypeDeclaration typeDeclaration){
        /*
         * Print comments to get proper line number
         */
        this.scribe.printComment();
        int line = this.scribe.line;

    this.scribe.printModifiers(typeDeclaration.annotations, this);

    if (this.scribe.line > line) {
          // annotations introduced new line, but this is not a line wrapping
      // see 158267
      line = this.scribe.line;
    }

        /*
     * Type name
     */
        switch(TypeDeclaration.kind(typeDeclaration.modifiers)) {
          case TypeDeclaration.CLASS_DECL :
        this.scribe.printNextToken(TerminalTokens.TokenNameclass, true);
            break;
          case TypeDeclaration.INTERFACE_DECL :
        this.scribe.printNextToken(TerminalTokens.TokenNameinterface, true);
            break;
          case TypeDeclaration.ENUM_DECL :
        this.scribe.printNextToken(TerminalTokens.TokenNameenum, true);
            break;
          case TypeDeclaration.ANNOTATION_TYPE_DECL :
        this.scribe.printNextToken(TerminalTokens.TokenNameAT, this.preferences.insert_space_before_at_in_annotation_type_declaration);
        this.scribe.printNextToken(TerminalTokens.TokenNameinterface, this.preferences.insert_space_after_at_in_annotation_type_declaration);
            break;
        }
    this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, true);

    TypeParameter[] typeParameters = typeDeclaration.typeParameters;
    if (typeParameters != null) {
      this.scribe.printNextToken(TerminalTokens.TokenNameLESS, this.preferences.insert_space_before_opening_angle_bracket_in_type_parameters);
      if (this.preferences.insert_space_after_opening_angle_bracket_in_type_parameters) {
        this.scribe.space();
      }
      int length = typeParameters.length;
      for (int i = 0; i < length - 1; i++) {
        typeParameters[i].traverse(this, typeDeclaration.scope);
        this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_type_parameters);
        if (this.preferences.insert_space_after_comma_in_type_parameters) {
          this.scribe.space();
        }       
      }
      typeParameters[length - 1].traverse(this, typeDeclaration.scope);
      if (isClosingGenericToken()) {
        this.scribe.printNextToken(CLOSING_GENERICS_EXPECTEDTOKENS, this.preferences.insert_space_before_closing_angle_bracket_in_type_parameters);
      }
      if (this.preferences.insert_space_after_closing_angle_bracket_in_type_parameters) {
        this.scribe.space();
      }
    }
    /*
     * Superclass
     */
    final TypeReference superclass = typeDeclaration.superclass;
    if (superclass != null) {
      Alignment superclassAlignment =this.scribe.createAlignment(
          "superclass", //$NON-NLS-1$
          this.preferences.alignment_for_superclass_in_type_declaration,
          2,
          this.scribe.scanner.currentPosition);
      this.scribe.enterAlignment(superclassAlignment);
      boolean ok = false;
      do {
        try {
          this.scribe.alignFragment(superclassAlignment, 0);
          this.scribe.printNextToken(TerminalTokens.TokenNameextends, true);
          this.scribe.alignFragment(superclassAlignment, 1);
          this.scribe.space();
          superclass.traverse(this, typeDeclaration.scope);
          ok = true;
        } catch (AlignmentException e) {
          this.scribe.redoAlignment(e);
        }
      } while (!ok);
      this.scribe.exitAlignment(superclassAlignment, true);
    }

    /*
     * Super Interfaces
     */
    final TypeReference[] superInterfaces = typeDeclaration.superInterfaces;
    if (superInterfaces != null) {
      int alignment_for_superinterfaces;
      int kind = TypeDeclaration.kind(typeDeclaration.modifiers);
      switch(kind) {
        case TypeDeclaration.ENUM_DECL :
          alignment_for_superinterfaces = this.preferences.alignment_for_superinterfaces_in_enum_declaration;
          break;
        default:
          alignment_for_superinterfaces = this.preferences.alignment_for_superinterfaces_in_type_declaration;
          break;
      }
      int superInterfaceLength = superInterfaces.length;
      Alignment interfaceAlignment =this.scribe.createAlignment(
          "superInterfaces",//$NON-NLS-1$
          alignment_for_superinterfaces,
          superInterfaceLength+1// implements token is first fragment
          this.scribe.scanner.currentPosition);
      this.scribe.enterAlignment(interfaceAlignment);
      boolean ok = false;
      do {
        try {
          this.scribe.alignFragment(interfaceAlignment, 0);
          if (kind == TypeDeclaration.INTERFACE_DECL) {
            this.scribe.printNextToken(TerminalTokens.TokenNameextends, true);
          } else  {
            this.scribe.printNextToken(TerminalTokens.TokenNameimplements, true);
          }
          for (int i = 0; i < superInterfaceLength; i++) {
            if (i > 0) {
              this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_superinterfaces);
              this.scribe.printTrailingComment();
              this.scribe.alignFragment(interfaceAlignment, i+1);
              if (this.preferences.insert_space_after_comma_in_superinterfaces) {
                this.scribe.space();
              }
              superInterfaces[i].traverse(this, typeDeclaration.scope);
            } else {
              this.scribe.alignFragment(interfaceAlignment, i+1);
              this.scribe.space();
              superInterfaces[i].traverse(this, typeDeclaration.scope);
            }
          }
          ok = true;
        } catch (AlignmentException e) {
          this.scribe.redoAlignment(e);
        }
      } while (!ok);
      this.scribe.exitAlignment(interfaceAlignment, true);
    }

    /*
     * Type body
     */
    String class_declaration_brace;
    boolean space_before_opening_brace;
    int kind = TypeDeclaration.kind(typeDeclaration.modifiers);
    switch(kind) {
      case TypeDeclaration.ENUM_DECL :
        class_declaration_brace = this.preferences.brace_position_for_enum_declaration;
        space_before_opening_brace = this.preferences.insert_space_before_opening_brace_in_enum_declaration;
        break;
      case TypeDeclaration.ANNOTATION_TYPE_DECL :
        class_declaration_brace = this.preferences.brace_position_for_annotation_type_declaration;
        space_before_opening_brace =  this.preferences.insert_space_before_opening_brace_in_annotation_type_declaration;
        break;
      default:
        class_declaration_brace = this.preferences.brace_position_for_type_declaration;
        space_before_opening_brace = this.preferences.insert_space_before_opening_brace_in_type_declaration;
        break;
    }
        formatLeftCurlyBrace(line, class_declaration_brace);
    formatTypeOpeningBrace(class_declaration_brace, space_before_opening_brace, typeDeclaration);
   
    boolean indent_body_declarations_compare_to_header;
    switch(kind) {
      case TypeDeclaration.ENUM_DECL :
        indent_body_declarations_compare_to_header = this.preferences.indent_body_declarations_compare_to_enum_declaration_header;
        break;
      case TypeDeclaration.ANNOTATION_TYPE_DECL :
        indent_body_declarations_compare_to_header = this.preferences.indent_body_declarations_compare_to_annotation_declaration_header;
        break;
      default:
        indent_body_declarations_compare_to_header = this.preferences.indent_body_declarations_compare_to_type_header;
        break;
    }   
    if (indent_body_declarations_compare_to_header) {
      this.scribe.indent();
    }
   
    if (kind == TypeDeclaration.ENUM_DECL) {
      FieldDeclaration[] fieldDeclarations = typeDeclaration.fields;
      boolean hasConstants = false;
      if (fieldDeclarations != null) {
        int length = fieldDeclarations.length;
        int enumConstantsLength = 0;
        for (int i = 0; i < length; i++) {
          FieldDeclaration fieldDeclaration = fieldDeclarations[i];
          if (fieldDeclaration.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT) {
            enumConstantsLength++;
          } else {
            break;
          }
        }
        hasConstants = enumConstantsLength != 0;
        if (enumConstantsLength > 1) {
          Alignment enumConstantsAlignment = this.scribe.createAlignment(
              "enumConstants",//$NON-NLS-1$
              this.preferences.alignment_for_enum_constants,
              enumConstantsLength,
              this.scribe.scanner.currentPosition,
              0, // we don't want to indent enum constants when splitting to a new line
              false);
          this.scribe.enterAlignment(enumConstantsAlignment);
          boolean ok = false;
          do {
            try {
              for (int i = 0; i < enumConstantsLength; i++) {
                this.scribe.alignFragment(enumConstantsAlignment, i);
                FieldDeclaration fieldDeclaration = fieldDeclarations[i];
                fieldDeclaration.traverse(this, typeDeclaration.initializerScope);
                if (isNextToken(TerminalTokens.TokenNameCOMMA)) {
                  this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_enum_declarations);
                  if (this.preferences.insert_space_after_comma_in_enum_declarations) {
                    this.scribe.space();
                  }
                  this.scribe.printTrailingComment();
                  if (fieldDeclaration.initialization instanceof QualifiedAllocationExpression) {
                    this.scribe.printNewLine();
                  }
                }
              }
              ok = true;
            } catch (AlignmentException e) {
              this.scribe.redoAlignment(e);
            }
          } while (!ok);
          this.scribe.exitAlignment(enumConstantsAlignment, true);
        } else {
          FieldDeclaration fieldDeclaration = fieldDeclarations[0];
          fieldDeclaration.traverse(this, typeDeclaration.initializerScope);
          if (isNextToken(TerminalTokens.TokenNameCOMMA)) {
            this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_enum_declarations);
            if (this.preferences.insert_space_after_comma_in_enum_declarations) {
              this.scribe.space();
            }
            this.scribe.printTrailingComment();
            if (fieldDeclaration.initialization instanceof QualifiedAllocationExpression) {
              this.scribe.printNewLine();
            }
          }
        }
      }
      if (isNextToken(TerminalTokens.TokenNameSEMICOLON)) {
        this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
        this.scribe.printTrailingComment();
      }
      if (hasConstants) {
        this.scribe.printNewLine()
      }
    }

    formatTypeMembers(typeDeclaration);
   
    if (indent_body_declarations_compare_to_header) {
      this.scribe.unIndent();
    }
   
    switch(kind) {
      case TypeDeclaration.ENUM_DECL :
        if (this.preferences.insert_new_line_in_empty_enum_declaration) {
          this.scribe.printNewLine();
        }
        break;
      case TypeDeclaration.ANNOTATION_TYPE_DECL :
        if (this.preferences.insert_new_line_in_empty_annotation_declaration) {
          this.scribe.printNewLine();
        }
        break;
      default :
        if (this.preferences.insert_new_line_in_empty_type_declaration) {
          this.scribe.printNewLine();
        }
    }
    this.scribe.printNextToken(TerminalTokens.TokenNameRBRACE);
    this.scribe.printTrailingComment();
    if (class_declaration_brace.equals(DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED)) {
      this.scribe.unIndent();
    }
    if (hasComments()) {
      this.scribe.printNewLine();
    }
  }

  private void format(
    TypeDeclaration memberTypeDeclaration,
    ClassScope scope,
    boolean isChunkStart,
    boolean isFirstClassBodyDeclaration) {

    if (isFirstClassBodyDeclaration) {
      int newLinesBeforeFirstClassBodyDeclaration = this.preferences.blank_lines_before_first_class_body_declaration;
      if (newLinesBeforeFirstClassBodyDeclaration > 0) {
        this.scribe.printEmptyLines(newLinesBeforeFirstClassBodyDeclaration);
      }
    } else {
      int newLineBeforeChunk = isChunkStart ? this.preferences.blank_lines_before_new_chunk : 0;
      if (newLineBeforeChunk > 0) {
        this.scribe.printEmptyLines(newLineBeforeChunk);
      }
      final int newLinesBeforeMember = this.preferences.blank_lines_before_member_type;
      if (newLinesBeforeMember > 0) {
        this.scribe.printEmptyLines(newLinesBeforeMember);
      }
    }
    memberTypeDeclaration.traverse(this, scope);
  }
 
  private void formatAnonymousTypeDeclaration(TypeDeclaration typeDeclaration) {
    /*
     * Type body
     */
    String anonymous_type_declaration_brace_position = this.preferences.brace_position_for_anonymous_type_declaration;
   
    formatTypeOpeningBrace(anonymous_type_declaration_brace_position, this.preferences.insert_space_before_opening_brace_in_anonymous_type_declaration, typeDeclaration);
   
    this.scribe.indent();

    formatTypeMembers(typeDeclaration);

    this.scribe.unIndent();
    if (this.preferences.insert_new_line_in_empty_anonymous_type_declaration) {
      this.scribe.printNewLine();
    }
    this.scribe.printNextToken(TerminalTokens.TokenNameRBRACE);
    if (anonymous_type_declaration_brace_position.equals(DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED)) {
      this.scribe.unIndent();
    }
  }
 
  /**
   * @param block
   * @param scope
   * @param block_brace_position
   */
  private void formatBlock(Block block, BlockScope scope, String block_brace_position, boolean insertSpaceBeforeOpeningBrace) {
    formatOpeningBrace(block_brace_position, insertSpaceBeforeOpeningBrace);
    final Statement[] statements = block.statements;
    if (statements != null) {
      this.scribe.printNewLine();
      if (this.preferences.indent_statements_compare_to_block) {
        this.scribe.indent();
      }
      formatStatements(scope, statements, true);
      this.scribe.printComment();
 
      if (this.preferences.indent_statements_compare_to_block) {
        this.scribe.unIndent();
      }
    } else if (this.preferences.insert_new_line_in_empty_block) {
      this.scribe.printNewLine();
      if (this.preferences.indent_statements_compare_to_block) {
        this.scribe.indent();
      }
      this.scribe.printComment();
 
      if (this.preferences.indent_statements_compare_to_block) {
        this.scribe.unIndent();
      }
    } else {
      if (this.preferences.indent_statements_compare_to_block) {
        this.scribe.indent();
      }
      this.scribe.printComment();
 
      if (this.preferences.indent_statements_compare_to_block) {
        this.scribe.unIndent();
      }
    }
    this.scribe.printNextToken(TerminalTokens.TokenNameRBRACE);
    this.scribe.printTrailingComment();
    if (DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED.equals(block_brace_position)) {
      this.scribe.unIndent();
    }
  }

  private void formatCascadingMessageSends(CascadingMethodInvocationFragmentBuilder builder, BlockScope scope) {
    int size = builder.size();
    MessageSend[] fragments = builder.fragments();
    Expression fragment = fragments[0].receiver;
    int startingPositionInCascade = 1;
    if (!fragment.isImplicitThis()) {
      fragment.traverse(this, scope);
    } else {
      MessageSend currentMessageSend = fragments[1];
      final int numberOfParens = (currentMessageSend.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
      if (numberOfParens > 0) {
        manageOpeningParenthesizedExpression(currentMessageSend, numberOfParens);
      }
      ASTNode[] arguments = currentMessageSend.arguments;
      TypeReference[] typeArguments = currentMessageSend.typeArguments;
      if (typeArguments != null) {
          this.scribe.printNextToken(TerminalTokens.TokenNameLESS, this.preferences.insert_space_before_opening_angle_bracket_in_type_arguments);
          if (this.preferences.insert_space_after_opening_angle_bracket_in_type_arguments) {
            this.scribe.space();
          }
          int length = typeArguments.length;
          for (int i = 0; i < length - 1; i++) {
            typeArguments[i].traverse(this, scope);
            this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_type_arguments);
            if (this.preferences.insert_space_after_comma_in_type_arguments) {
              this.scribe.space();
            }       
          }
          typeArguments[length - 1].traverse(this, scope);
          if (isClosingGenericToken()) {
            this.scribe.printNextToken(CLOSING_GENERICS_EXPECTEDTOKENS, this.preferences.insert_space_before_closing_angle_bracket_in_type_arguments);
          }
          if (this.preferences.insert_space_after_closing_angle_bracket_in_type_arguments) {
            this.scribe.space();
          }
      }
      this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier); // selector
      this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_method_invocation);
      if (arguments != null) {
        if (this.preferences.insert_space_after_opening_paren_in_method_invocation) {
          this.scribe.space();
        }
        int argumentLength = arguments.length;
        Alignment argumentsAlignment = this.scribe.createAlignment(
            "messageArguments", //$NON-NLS-1$
            this.preferences.alignment_for_arguments_in_method_invocation,
            Alignment.R_OUTERMOST,
            argumentLength,
            this.scribe.scanner.currentPosition);
        this.scribe.enterAlignment(argumentsAlignment);
        boolean okForArguments = false;
        do {
          try {
            for (int j = 0; j < argumentLength; j++) {
              if (j > 0) {
                this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_method_invocation_arguments);
                this.scribe.printTrailingComment();
              }
              this.scribe.alignFragment(argumentsAlignment, j);
              if (j > 0 && this.preferences.insert_space_after_comma_in_method_invocation_arguments) {
                this.scribe.space();
              }
              arguments[j].traverse(this, scope);
            }
            okForArguments = true;
          } catch (AlignmentException e) {
            this.scribe.redoAlignment(e);
          }
        } while (!okForArguments);
        this.scribe.exitAlignment(argumentsAlignment, true);
        this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_method_invocation);
      } else {
        this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_between_empty_parens_in_method_invocation);
      }
      if (numberOfParens > 0) {
        manageClosingParenthesizedExpression(currentMessageSend, numberOfParens);
      }
      startingPositionInCascade = 2;
    }
    Alignment cascadingMessageSendAlignment =
      this.scribe.createAlignment(
        "cascadingMessageSendAlignment", //$NON-NLS-1$
        this.preferences.alignment_for_selector_in_method_invocation,
        Alignment.R_INNERMOST,
        size,
        this.scribe.scanner.currentPosition);
    this.scribe.enterAlignment(cascadingMessageSendAlignment);
    boolean ok = false;
    do {
      try {
        this.scribe.alignFragment(cascadingMessageSendAlignment, 0);
        this.scribe.printNextToken(TerminalTokens.TokenNameDOT);
        for (int i = startingPositionInCascade; i < size; i++) {
          MessageSend currentMessageSend = fragments[i];
          final int numberOfParens = (currentMessageSend.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
          if (numberOfParens > 0) {
            manageOpeningParenthesizedExpression(currentMessageSend, numberOfParens);
          }
          TypeReference[] typeArguments = currentMessageSend.typeArguments;
          if (typeArguments != null) {
              this.scribe.printNextToken(TerminalTokens.TokenNameLESS, this.preferences.insert_space_before_opening_angle_bracket_in_type_arguments);
              if (this.preferences.insert_space_after_opening_angle_bracket_in_type_arguments) {
                this.scribe.space();
              }
              int length = typeArguments.length;
              for (int j = 0; j < length - 1; j++) {
                typeArguments[j].traverse(this, scope);
                this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_type_arguments);
                if (this.preferences.insert_space_after_comma_in_type_arguments) {
                  this.scribe.space();
                }       
              }
              typeArguments[length - 1].traverse(this, scope);
              if (isClosingGenericToken()) {
                this.scribe.printNextToken(CLOSING_GENERICS_EXPECTEDTOKENS, this.preferences.insert_space_before_closing_angle_bracket_in_type_arguments);
              }
              if (this.preferences.insert_space_after_closing_angle_bracket_in_type_arguments) {
                this.scribe.space();
              }
          }
          ASTNode[] arguments = currentMessageSend.arguments;
          this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier); // selector
          this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_method_invocation);
          if (arguments != null) {
            if (this.preferences.insert_space_after_opening_paren_in_method_invocation) {
              this.scribe.space();
            }
            int argumentLength = arguments.length;
            Alignment argumentsAlignment = this.scribe.createAlignment(
                "messageArguments", //$NON-NLS-1$
                this.preferences.alignment_for_arguments_in_method_invocation,
                Alignment.R_OUTERMOST,
                argumentLength,
                this.scribe.scanner.currentPosition);
            this.scribe.enterAlignment(argumentsAlignment);
            boolean okForArguments = false;
            do {
              try {
                for (int j = 0; j < argumentLength; j++) {
                  if (j > 0) {
                    this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_method_invocation_arguments);
                    this.scribe.printTrailingComment();
                  }
                  this.scribe.alignFragment(argumentsAlignment, j);
                  if (j > 0 && this.preferences.insert_space_after_comma_in_method_invocation_arguments) {
                    this.scribe.space();
                  }
                  arguments[j].traverse(this, scope);
                }
                okForArguments = true;
              } catch (AlignmentException e) {
                this.scribe.redoAlignment(e);
              }
            } while (!okForArguments);
            this.scribe.exitAlignment(argumentsAlignment, true);
            this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_method_invocation);
          } else {
            this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_between_empty_parens_in_method_invocation);
          }
          if (numberOfParens > 0) {
            manageClosingParenthesizedExpression(currentMessageSend, numberOfParens);
          }
          if (i < size - 1) {
            this.scribe.alignFragment(cascadingMessageSendAlignment, i);
            this.scribe.printNextToken(TerminalTokens.TokenNameDOT);
          }
        }
        ok = true;
      } catch(AlignmentException e){
        this.scribe.redoAlignment(e);
      }
    } while (!ok);   
    this.scribe.exitAlignment(cascadingMessageSendAlignment, true);
  }
 
  /*
   * Merged traversal of member (types, fields, methods)
   */
  private void formatClassBodyDeclarations(ASTNode[] nodes) {
    final int FIELD = 1, METHOD = 2, TYPE = 3;
    this.scribe.lastNumberOfNewLines = 1;
    ASTNode[] mergedNodes = computeMergedMemberDeclarations(nodes);
    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$
    this.scribe.enterMemberAlignment(memberAlignment);
    boolean isChunkStart = false;
    boolean ok = false;
    int startIndex = 0;
    do {
      try {
        for (int i = startIndex, max = mergedNodes.length; i < max; i++) {
          ASTNode member = mergedNodes[i];
          if (member instanceof FieldDeclaration) {
            isChunkStart = memberAlignment.checkChunkStart(FIELD, i, this.scribe.scanner.currentPosition);
            if (member instanceof MultiFieldDeclaration){
              MultiFieldDeclaration multiField = (MultiFieldDeclaration) member;
              format(multiField, this, null, isChunkStart, i == 0);
            } else if (member instanceof Initializer) {
              int newLineBeforeChunk = isChunkStart ? this.preferences.blank_lines_before_new_chunk : 0;
              if (newLineBeforeChunk > 0 && i != 0) {
                this.scribe.printEmptyLines(newLineBeforeChunk);
              } else if (i == 0) {
                int newLinesBeforeFirstClassBodyDeclaration = this.preferences.blank_lines_before_first_class_body_declaration;
                if (newLinesBeforeFirstClassBodyDeclaration > 0) {
                  this.scribe.printEmptyLines(newLinesBeforeFirstClassBodyDeclaration);
                }
              }
              Initializer initializer = (Initializer) member;
              initializer.traverse(this, null);
            } else {
              FieldDeclaration field = (FieldDeclaration) member;
              format(field, this, null, isChunkStart, i == 0);
            }
          } else if (member instanceof AbstractMethodDeclaration) {
            isChunkStart = memberAlignment.checkChunkStart(METHOD, i, this.scribe.scanner.currentPosition);
            format((AbstractMethodDeclaration) member, null, isChunkStart, i == 0);
          } else {
            isChunkStart = memberAlignment.checkChunkStart(TYPE, i, this.scribe.scanner.currentPosition);
            format((TypeDeclaration)member, null, isChunkStart, i == 0);
          }
          if (isNextToken(TerminalTokens.TokenNameSEMICOLON)) {
            this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
            this.scribe.printTrailingComment();
          }
          if (i != max - 1) {
            this.scribe.printNewLine();
          }
        }
        ok = true;
      } catch(AlignmentException e){
        startIndex = memberAlignment.chunkStartIndex;
        this.scribe.redoMemberAlignment(e);
      }
    } while (!ok);   
    this.scribe.exitMemberAlignment(memberAlignment);
    if (hasComments()) {
      this.scribe.printNewLine();
    }
    this.scribe.printComment();
  }

  private void formatEmptyTypeDeclaration(boolean isFirst) {
    boolean hasSemiColon = isNextToken(TerminalTokens.TokenNameSEMICOLON);
    while(isNextToken(TerminalTokens.TokenNameSEMICOLON)) {
      this.scribe.printComment();
      this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
      this.scribe.printTrailingComment();
    }
    if (hasSemiColon && isFirst) {
      this.scribe.printNewLine();
    }
  }

  private void formatGuardClauseBlock(Block block, BlockScope scope) {

    this.scribe.printNextToken(TerminalTokens.TokenNameLBRACE, this.preferences.insert_space_before_opening_brace_in_block);
    this.scribe.space();

    final Statement[] statements = block.statements;
    statements[0].traverse(this, scope);
    this.scribe.printNextToken(TerminalTokens.TokenNameRBRACE, true);
    this.scribe.printTrailingComment();
  }

    private void formatLeftCurlyBrace(final int line, final String bracePosition) {
        /*
         * deal with (quite unexpected) comments right before lcurly
         */
        this.scribe.printComment();
        if (DefaultCodeFormatterConstants.NEXT_LINE_ON_WRAP.equals(bracePosition)
                && (this.scribe.line > line || this.scribe.column >= this.preferences.page_width))
        {
            this.scribe.printNewLine();
        }
    }
   
  private void formatLocalDeclaration(LocalDeclaration localDeclaration, BlockScope scope, boolean insertSpaceBeforeComma, boolean insertSpaceAfterComma) {

    if (!isMultipleLocalDeclaration(localDeclaration)) {
      if (localDeclaration.modifiers != NO_MODIFIERS || localDeclaration.annotations != null) {
            this.scribe.printComment();
        this.scribe.printModifiers(localDeclaration.annotations, this);
        this.scribe.space();
      }
 
      /*
       * Argument type
       */   
      if (localDeclaration.type != null) {
        localDeclaration.type.traverse(this, scope);
      }
      /*
       * Print the argument name
       */
      this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, true);
    } else {
      /*
       * Print the argument name
       */
      this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, false);
    }
    /*
     * Check for extra dimensions
     */
    int extraDimensions = getDimensions();
    if (extraDimensions != 0) {
       for (int index = 0; index < extraDimensions; index++) {
         this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET);
         this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET);
       }
    }
 
    final Expression initialization = localDeclaration.initialization;
    if (initialization != null) {
      /*
       * Print the method name
       */ 
      this.scribe.printNextToken(TerminalTokens.TokenNameEQUAL, this.preferences.insert_space_before_assignment_operator);
      if (this.preferences.insert_space_after_assignment_operator) {
        this.scribe.space();
      }
      Alignment assignmentAlignment = this.scribe.createAlignment("localDeclarationAssignmentAlignment", this.preferences.alignment_for_assignment, Alignment.R_OUTERMOST, 1, this.scribe.scanner.currentPosition); //$NON-NLS-1$
      this.scribe.enterAlignment(assignmentAlignment);
      boolean ok = false;
      do {
        try {
          this.scribe.alignFragment(assignmentAlignment, 0);
          initialization.traverse(this, scope);
          ok = true;
        } catch(AlignmentException e){
          this.scribe.redoAlignment(e);
        }
      } while (!ok);   
      this.scribe.exitAlignment(assignmentAlignment, true);     
    }

    if (isPartOfMultipleLocalDeclaration()) {
      this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, insertSpaceBeforeComma);
      if (insertSpaceAfterComma) {
        this.scribe.space();
      }
      this.scribe.printTrailingComment();
    }
  }

  private void formatMessageSend(
    MessageSend messageSend,
    BlockScope scope,
    Alignment messageAlignment) {

    if (messageAlignment != null) {
      this.scribe.alignFragment(messageAlignment, 0);
      this.scribe.printNextToken(TerminalTokens.TokenNameDOT);
    }
    TypeReference[] typeArguments = messageSend.typeArguments;
    if (typeArguments != null) {
        this.scribe.printNextToken(TerminalTokens.TokenNameLESS, this.preferences.insert_space_before_opening_angle_bracket_in_type_arguments);
        if (this.preferences.insert_space_after_opening_angle_bracket_in_type_arguments) {
          this.scribe.space();
        }
        int length = typeArguments.length;
        for (int i = 0; i < length - 1; i++) {
          typeArguments[i].traverse(this, scope);
          this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_type_arguments);
          if (this.preferences.insert_space_after_comma_in_type_arguments) {
            this.scribe.space();
          }       
        }
        typeArguments[length - 1].traverse(this, scope);
        if (isClosingGenericToken()) {
          this.scribe.printNextToken(CLOSING_GENERICS_EXPECTEDTOKENS, this.preferences.insert_space_before_closing_angle_bracket_in_type_arguments);
        }
        if (this.preferences.insert_space_after_closing_angle_bracket_in_type_arguments) {
          this.scribe.space();
        }
    }
    this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier); // selector
    this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_method_invocation);

    final Expression[] arguments = messageSend.arguments;
    if (arguments != null) {
      if (this.preferences.insert_space_after_opening_paren_in_method_invocation) {
        this.scribe.space();
      }
      int argumentsLength = arguments.length;
      if (argumentsLength > 1) {
        Alignment argumentsAlignment = this.scribe.createAlignment(
            "messageArguments", //$NON-NLS-1$
            this.preferences.alignment_for_arguments_in_method_invocation,
            argumentsLength,
            this.scribe.scanner.currentPosition);
        this.scribe.enterAlignment(argumentsAlignment);
        boolean ok = false;
        do {
          try {
            for (int i = 0; i < argumentsLength; i++) {
              if (i > 0) {
                this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_method_invocation_arguments);
                this.scribe.printTrailingComment();
              }
              this.scribe.alignFragment(argumentsAlignment, i);
              if (i > 0 && this.preferences.insert_space_after_comma_in_method_invocation_arguments) {
                this.scribe.space();
              }
              arguments[i].traverse(this, scope);
            }
            ok = true;
          } catch (AlignmentException e) {
            this.scribe.redoAlignment(e);
          }
        } while (!ok);
        this.scribe.exitAlignment(argumentsAlignment, true);
      } else {
        for (int i = 0; i < argumentsLength; i++) {
          if (i > 0) {
            this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_method_invocation_arguments);
            this.scribe.printTrailingComment();
          }
          if (i > 0 && this.preferences.insert_space_after_comma_in_method_invocation_arguments) {
            this.scribe.space();
          }
          arguments[i].traverse(this, scope);
        }
      }
      this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_method_invocation);
    } else {
      this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_between_empty_parens_in_method_invocation);
    }
  }

  private void formatMethodArguments(
      AbstractMethodDeclaration methodDeclaration,
      boolean spaceBeforeOpenParen,
      boolean spaceBetweenEmptyParameters,
      boolean spaceBeforeClosingParen,
      boolean spaceBeforeFirstParameter,
      boolean spaceBeforeComma,
      boolean spaceAfterComma,
      int methodDeclarationParametersAlignment) {
       
    this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, spaceBeforeOpenParen);
   
    final Argument[] arguments = methodDeclaration.arguments;
    if (arguments != null) {
      if (spaceBeforeFirstParameter) {
        this.scribe.space();
      }
      int argumentLength = arguments.length;
      Alignment argumentsAlignment = this.scribe.createAlignment(
          "methodArguments",//$NON-NLS-1$
          methodDeclarationParametersAlignment,
          argumentLength,
          this.scribe.scanner.currentPosition);
      this.scribe.enterAlignment(argumentsAlignment);
      boolean ok = false;
      do {
        try {
          for (int i = 0; i < argumentLength; i++) {
            if (i > 0) {
              this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, spaceBeforeComma);
              this.scribe.printTrailingComment();
            }
            this.scribe.alignFragment(argumentsAlignment, i);
            if (i > 0 && spaceAfterComma) {
              this.scribe.space();
            }
            arguments[i].traverse(this, methodDeclaration.scope);
          }
          ok = true;
        } catch (AlignmentException e) {
          this.scribe.redoAlignment(e);
        }
      } while (!ok);
      this.scribe.exitAlignment(argumentsAlignment, true);
   
      this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, spaceBeforeClosingParen);
    } else {
      this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, spaceBetweenEmptyParameters);
   
  }

  private void formatEnumConstantArguments(
      FieldDeclaration enumConstant,
      boolean spaceBeforeOpenParen,
      boolean spaceBetweenEmptyParameters,
      boolean spaceBeforeClosingParen,
      boolean spaceBeforeFirstParameter,
      boolean spaceBeforeComma,
      boolean spaceAfterComma,
      int methodDeclarationParametersAlignment) {
       
    if (!isNextToken(TerminalTokens.TokenNameLPAREN)) {
      return;
    }
   
    this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, spaceBeforeOpenParen);
    final Expression[] arguments = ((AllocationExpression) enumConstant.initialization).arguments;
    if (arguments != null) {
      int argumentLength = arguments.length;
      Alignment argumentsAlignment = this.scribe.createAlignment(
          "enumConstantArguments",//$NON-NLS-1$
          methodDeclarationParametersAlignment,
          argumentLength,
          this.scribe.scanner.currentPosition);
      this.scribe.enterAlignment(argumentsAlignment);
      boolean ok = false;
      do {
        try {
          if (spaceBeforeFirstParameter) {
            this.scribe.space();
          }
          for (int i = 0; i < argumentLength; i++) {
            if (i > 0) {
              this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, spaceBeforeComma);
              this.scribe.printTrailingComment();
            }
            this.scribe.alignFragment(argumentsAlignment, i);
            if (i > 0 && spaceAfterComma) {
              this.scribe.space();
            }
            arguments[i].traverse(this, (BlockScope) null);
          }
          ok = true;
        } catch (AlignmentException e) {
          this.scribe.redoAlignment(e);
        }
      } while (!ok);
      this.scribe.exitAlignment(argumentsAlignment, true);
   
      this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, spaceBeforeClosingParen);
    } else {
      this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, spaceBetweenEmptyParameters);
   
  }

  private void formatNecessaryEmptyStatement() {
    if (this.preferences.put_empty_statement_on_new_line) {
      this.scribe.printNewLine();
      this.scribe.indent();
      this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
      this.scribe.printTrailingComment();
      this.scribe.unIndent();
    } else {
      this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
      this.scribe.printTrailingComment();
    }
  }
 
  private void formatOpeningBrace(String bracePosition, boolean insertSpaceBeforeBrace) {
 
    if (DefaultCodeFormatterConstants.NEXT_LINE.equals(bracePosition)) {
      this.scribe.printNewLine();
    } else if (DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED.equals(bracePosition)) {
      this.scribe.printNewLine();
      this.scribe.indent();
    }
    this.scribe.printNextToken(TerminalTokens.TokenNameLBRACE, insertSpaceBeforeBrace);

    this.scribe.printTrailingComment();
  }
  private void formatStatements(BlockScope scope, final Statement[] statements, boolean insertNewLineAfterLastStatement) {
    int statementsLength = statements.length;
    for (int i = 0; i < statementsLength; i++) {
      final Statement statement = statements[i];
      if (i > 0 && (statements[i - 1] instanceof EmptyStatement) && !(statement instanceof EmptyStatement)) {
        this.scribe.printNewLine();
      }
      statement.traverse(this, scope);
      if (statement instanceof Expression) {
        this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
        this.scribe.printTrailingComment();
        if (i != statementsLength - 1) {
          if (!(statement instanceof EmptyStatement) && !(statements[i + 1] instanceof EmptyStatement)) {
            this.scribe.printNewLine();
          }
        } else if (i == statementsLength - 1 && insertNewLineAfterLastStatement) {
          this.scribe.printNewLine();
        }
      } else if (statement instanceof LocalDeclaration) {
        LocalDeclaration currentLocal = (LocalDeclaration) statement;
        if (i < (statementsLength - 1)) {
          /*
           * We need to check that the next statement is a local declaration
           */
          if (statements[i + 1] instanceof LocalDeclaration) {
            LocalDeclaration nextLocal = (LocalDeclaration) statements[i + 1];
            if (currentLocal.declarationSourceStart != nextLocal.declarationSourceStart) {
              this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
              this.scribe.printTrailingComment();
              if (i != statementsLength - 1) {
                if (!(statement instanceof EmptyStatement) && !(statements[i + 1] instanceof EmptyStatement)) {
                  this.scribe.printNewLine();
                }
              } else if (i == statementsLength - 1 && insertNewLineAfterLastStatement) {
                this.scribe.printNewLine();
              }
            }
          } else {
            this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
            this.scribe.printTrailingComment();
            if (i != statementsLength - 1) {
              if (!(statement instanceof EmptyStatement) && !(statements[i + 1] instanceof EmptyStatement)) {
                this.scribe.printNewLine();
              }
            } else if (i == statementsLength - 1 && insertNewLineAfterLastStatement) {
              this.scribe.printNewLine();
            }
          }
        } else {
          this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
          this.scribe.printTrailingComment();
          if (i != statementsLength - 1) {
            if (!(statement instanceof EmptyStatement) && !(statements[i + 1] instanceof EmptyStatement)) {
              this.scribe.printNewLine();
            }
          } else if (i == statementsLength - 1 && insertNewLineAfterLastStatement) {
            this.scribe.printNewLine();
          }
        }
      } else if (i != statementsLength - 1) {
        if (!(statement instanceof EmptyStatement) && !(statements[i + 1] instanceof EmptyStatement)) {
          this.scribe.printNewLine();
        }
      } else if (i == statementsLength - 1 && insertNewLineAfterLastStatement) {
        this.scribe.printNewLine();
      }
    }
  }
 
  private void formatThrowsClause(
    AbstractMethodDeclaration methodDeclaration,
    boolean spaceBeforeComma,
    boolean spaceAfterComma,
    int alignmentForThrowsClause) {
     
    final TypeReference[] thrownExceptions = methodDeclaration.thrownExceptions;
    if (thrownExceptions != null) {
      int thrownExceptionsLength = thrownExceptions.length;
      Alignment throwsAlignment = this.scribe.createAlignment(
          "throws",//$NON-NLS-1$
          alignmentForThrowsClause,
          thrownExceptionsLength, // throws is the first token
          this.scribe.scanner.currentPosition);
   
      this.scribe.enterAlignment(throwsAlignment);
      boolean ok = false;
      do {
        try {
          this.scribe.alignFragment(throwsAlignment, 0);
          this.scribe.printNextToken(TerminalTokens.TokenNamethrows, true);
   
          for (int i = 0; i < thrownExceptionsLength; i++) {
            if (i > 0) {
              this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, spaceBeforeComma);
              this.scribe.printTrailingComment();
              this.scribe.alignFragment(throwsAlignment, i);
              if (spaceAfterComma) {
                this.scribe.space();
              }
            } else {
              this.scribe.space();
            }
            thrownExceptions[i].traverse(this, methodDeclaration.scope);
          }
          ok = true;
        } catch (AlignmentException e) {
          this.scribe.redoAlignment(e);
        }
      } while (!ok);
      this.scribe.exitAlignment(throwsAlignment, true);
    }
  }

  /*
   * Merged traversal of member (types, fields, methods)
   */
  private void formatTypeMembers(TypeDeclaration typeDeclaration) {
    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$
    this.scribe.enterMemberAlignment(memberAlignment);
    ASTNode[] members = computeMergedMemberDeclarations(typeDeclaration);
    boolean isChunkStart = false;
    boolean ok = false;
    int startIndex = 0;
    do {
      try {
        for (int i = startIndex, max = members.length; i < max; i++) {
          ASTNode member = members[i];
          if (member instanceof FieldDeclaration) {
            isChunkStart = memberAlignment.checkChunkStart(Alignment.CHUNK_FIELD, i, this.scribe.scanner.currentPosition);
            if (member instanceof MultiFieldDeclaration) {
              MultiFieldDeclaration multiField = (MultiFieldDeclaration) member;
             
              if (multiField.isStatic()) {
                format(multiField, this, typeDeclaration.staticInitializerScope, isChunkStart, i == 0);
              } else {
                format(multiField, this, typeDeclaration.initializerScope, isChunkStart, i == 0);
              }         
            } else if (member instanceof Initializer) {
              int newLineBeforeChunk = isChunkStart ? this.preferences.blank_lines_before_new_chunk : 0;
              if (newLineBeforeChunk > 0 && i != 0) {
                this.scribe.printEmptyLines(newLineBeforeChunk);
              } else if (i == 0) {
                int newLinesBeforeFirstClassBodyDeclaration = this.preferences.blank_lines_before_first_class_body_declaration;
                if (newLinesBeforeFirstClassBodyDeclaration > 0) {
                  this.scribe.printEmptyLines(newLinesBeforeFirstClassBodyDeclaration);
                }
              }
              Initializer initializer = (Initializer) member;
              if (initializer.isStatic()) {
                initializer.traverse(this, typeDeclaration.staticInitializerScope);
              } else {
                initializer.traverse(this, typeDeclaration.initializerScope);
              }         
            } else {
              FieldDeclaration field = (FieldDeclaration) member;
              if (field.isStatic()) {
                format(field, this, typeDeclaration.staticInitializerScope, isChunkStart, i == 0);
              } else {
                format(field, this, typeDeclaration.initializerScope, isChunkStart, i == 0);
              }         
            }
          } else if (member instanceof AbstractMethodDeclaration) {
            isChunkStart = memberAlignment.checkChunkStart(Alignment.CHUNK_METHOD, i, this.scribe.scanner.currentPosition);
            format((AbstractMethodDeclaration) member, typeDeclaration.scope, isChunkStart, i == 0);
          } else if (member instanceof TypeDeclaration) {
            isChunkStart = memberAlignment.checkChunkStart(Alignment.CHUNK_TYPE, i, this.scribe.scanner.currentPosition);
            format((TypeDeclaration)member, typeDeclaration.scope, isChunkStart, i == 0);
          }
          if (isNextToken(TerminalTokens.TokenNameSEMICOLON)) {
            this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
            this.scribe.printTrailingComment();
          }
          this.scribe.printNewLine();
          // realign to the proper value
          if (this.scribe.memberAlignment != null) {
            // select the last alignment
            this.scribe.indentationLevel = this.scribe.memberAlignment.originalIndentationLevel;
          }
        }
        ok = true;
      } catch(AlignmentException e){
        startIndex = memberAlignment.chunkStartIndex;
        this.scribe.redoMemberAlignment(e);
      }
    } while (!ok);
    this.scribe.printComment();
    this.scribe.exitMemberAlignment(memberAlignment);
  }

  private void formatTypeOpeningBraceForEnumConstant(String bracePosition, boolean insertSpaceBeforeBrace, TypeDeclaration typeDeclaration) {
    int fieldCount = (typeDeclaration.fields == null) ? 0 : typeDeclaration.fields.length;
    int methodCount = (typeDeclaration.methods == null) ? 0 : typeDeclaration.methods.length;
    int typeCount = (typeDeclaration.memberTypes == null) ? 0 : typeDeclaration.memberTypes.length;
 
    if (methodCount <= 2) {
      for (int i = 0, max = methodCount; i < max; i++) {
        final AbstractMethodDeclaration abstractMethodDeclaration = typeDeclaration.methods[i];
        if (abstractMethodDeclaration.isDefaultConstructor()) {
          methodCount--;
        } else if (abstractMethodDeclaration.isClinit()) {
          methodCount--;
        }
      }
    }
    final int memberLength = fieldCount + methodCount+typeCount;

    boolean insertNewLine = memberLength > 0;
   
    if (!insertNewLine) {
      if ((typeDeclaration.bits & ASTNode.IsAnonymousType) != 0) {
        insertNewLine = this.preferences.insert_new_line_in_empty_enum_constant;
      }
    }
 
    formatOpeningBrace(bracePosition, insertSpaceBeforeBrace);
   
    if (insertNewLine) {
      this.scribe.printNewLine();
    }
  }
  private void formatTypeOpeningBrace(String bracePosition, boolean insertSpaceBeforeBrace, TypeDeclaration typeDeclaration) {
    int fieldCount = (typeDeclaration.fields == null) ? 0 : typeDeclaration.fields.length;
    int methodCount = (typeDeclaration.methods == null) ? 0 : typeDeclaration.methods.length;
    int typeCount = (typeDeclaration.memberTypes == null) ? 0 : typeDeclaration.memberTypes.length;
 
    if (methodCount <= 2) {
      for (int i = 0, max = methodCount; i < max; i++) {
        final AbstractMethodDeclaration abstractMethodDeclaration = typeDeclaration.methods[i];
        if (abstractMethodDeclaration.isDefaultConstructor()) {
          methodCount--;
        } else if (abstractMethodDeclaration.isClinit()) {
          methodCount--;
        }
      }
    }
    final int memberLength = fieldCount + methodCount + typeCount;

    boolean insertNewLine = memberLength > 0;
   
    if (!insertNewLine) {
      if (TypeDeclaration.kind(typeDeclaration.modifiers) == TypeDeclaration.ENUM_DECL) {
        insertNewLine = this.preferences.insert_new_line_in_empty_enum_declaration;
      } else if ((typeDeclaration.bits & ASTNode.IsAnonymousType) != 0) {
        insertNewLine = this.preferences.insert_new_line_in_empty_anonymous_type_declaration;
      } else if (TypeDeclaration.kind(typeDeclaration.modifiers) == TypeDeclaration.ANNOTATION_TYPE_DECL) {
        insertNewLine = this.preferences.insert_new_line_in_empty_annotation_declaration;
      } else {
        insertNewLine = this.preferences.insert_new_line_in_empty_type_declaration;       
      }
    }
 
    formatOpeningBrace(bracePosition, insertSpaceBeforeBrace);
   
    if (insertNewLine) {
      this.scribe.printNewLine();
    }
  }
  private int getDimensions() {

    this.localScanner.resetTo(this.scribe.scanner.currentPosition, this.scribe.scannerEndPosition - 1);
    int dimensions = 0;
    int balance = 0;
    try {
      int token;
      loop: while ((token = this.localScanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
        switch(token) {
          case TerminalTokens.TokenNameRBRACKET:
            dimensions++;
            balance--;
            break;
          case TerminalTokens.TokenNameCOMMENT_BLOCK :
          case TerminalTokens.TokenNameCOMMENT_JAVADOC :
          case TerminalTokens.TokenNameCOMMENT_LINE :
            break;
          case TerminalTokens.TokenNameLBRACKET :
            balance++;
            break;
          default:
            break loop;
        }
      }
    } catch(InvalidInputException e) {
      // ignore
    }
    if (balance == 0) {
      return dimensions;
    }
    return 0;
  }

  private boolean hasComments() {

    this.localScanner.resetTo(this.scribe.scanner.startPosition, this.scribe.scannerEndPosition - 1);
    try {
      switch(this.localScanner.getNextToken()) {
        case TerminalTokens.TokenNameCOMMENT_BLOCK :
        case TerminalTokens.TokenNameCOMMENT_JAVADOC :
        case TerminalTokens.TokenNameCOMMENT_LINE :
          return true;
      }
    } catch(InvalidInputException e) {
      // ignore
    }
    return false;
  }

  private boolean isNextToken(int tokenName) {
    this.localScanner.resetTo(this.scribe.scanner.currentPosition, this.scribe.scannerEndPosition - 1);
    try {
      int token = this.localScanner.getNextToken();
      loop: while(true) {
        switch(token) {
          case TerminalTokens.TokenNameCOMMENT_BLOCK :
          case TerminalTokens.TokenNameCOMMENT_JAVADOC :
          case TerminalTokens.TokenNameCOMMENT_LINE :
            token = this.localScanner.getNextToken();
            continue loop;
          default:
            break loop;
        }
      }
      return  token == tokenName;
    } catch(InvalidInputException e) {
      // ignore
    }
    return false;
  }

  private boolean isClosingGenericToken() {
    this.localScanner.resetTo(this.scribe.scanner.currentPosition, this.scribe.scannerEndPosition - 1);
    try {
      int token = this.localScanner.getNextToken();
      loop: while(true) {
        switch(token) {
          case TerminalTokens.TokenNameCOMMENT_BLOCK :
          case TerminalTokens.TokenNameCOMMENT_JAVADOC :
          case TerminalTokens.TokenNameCOMMENT_LINE :
            token = this.localScanner.getNextToken();
            continue loop;
          default:
            break loop;
        }
      }
      switch(token) {
        case TerminalTokens.TokenNameGREATER :
        case TerminalTokens.TokenNameRIGHT_SHIFT :
        case TerminalTokens.TokenNameUNSIGNED_RIGHT_SHIFT :
          return true;
      }
    } catch(InvalidInputException e) {
      // ignore
    }
    return false;
  }

  private boolean isGuardClause(Block block) {
    return !commentStartsBlock(block.sourceStart, block.sourceEnd)
        && block.statements != null
        && block.statements.length == 1
        && (block.statements[0] instanceof ReturnStatement || block.statements[0] instanceof ThrowStatement);
  }

  private boolean isMultipleLocalDeclaration(LocalDeclaration localDeclaration) {

    if (localDeclaration.declarationSourceStart == this.lastLocalDeclarationSourceStart) return true;
    this.lastLocalDeclarationSourceStart = localDeclaration.declarationSourceStart;
    return false;
  }

  private boolean isPartOfMultipleLocalDeclaration() {
    this.localScanner.resetTo(this.scribe.scanner.currentPosition, this.scribe.scannerEndPosition - 1);
    try {
      int token;
      while ((token = this.localScanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
        switch(token) {
          case TerminalTokens.TokenNameCOMMA ://90
            return true;
          case TerminalTokens.TokenNameCOMMENT_BLOCK :
          case TerminalTokens.TokenNameCOMMENT_JAVADOC :
          case TerminalTokens.TokenNameCOMMENT_LINE :
            break;
          default:
            return false;
        }
      }
    } catch(InvalidInputException e) {
      // ignore
    }
    return false;
  }

  private void manageClosingParenthesizedExpression(Expression expression, int numberOfParens) {
    for (int i = 0; i < numberOfParens; i++) {
      this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_parenthesized_expression);
    }
  }

  private void manageOpeningParenthesizedExpression(Expression expression, int numberOfParens) {
    for (int i = 0; i < numberOfParens; i++) {
      this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_parenthesized_expression);
      if (this.preferences.insert_space_after_opening_paren_in_parenthesized_expression) {
        this.scribe.space();
      }
    }
  }
     
  /**
   * @see org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.aspectj.org.eclipse.jdt.internal.compiler.ast.AllocationExpression, org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope)
   */
  public boolean visit(
    AllocationExpression allocationExpression,
    BlockScope scope) {
    // 'new' ClassType '(' ArgumentListopt ')' ClassBodyopt

    final int numberOfParens = (allocationExpression.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
    if (numberOfParens > 0) {
      manageOpeningParenthesizedExpression(allocationExpression, numberOfParens);
    }
    this.scribe.printNextToken(TerminalTokens.TokenNamenew);
    TypeReference[] typeArguments = allocationExpression.typeArguments;
    if (typeArguments != null) {
        this.scribe.printNextToken(TerminalTokens.TokenNameLESS, this.preferences.insert_space_before_opening_angle_bracket_in_type_arguments);
        if (this.preferences.insert_space_after_opening_angle_bracket_in_type_arguments) {
          this.scribe.space();
        }
        int length = typeArguments.length;
        for (int i = 0; i < length - 1; i++) {
          typeArguments[i].traverse(this, scope);
          this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_type_arguments);
          if (this.preferences.insert_space_after_comma_in_type_arguments) {
            this.scribe.space();
          }       
        }
        typeArguments[length - 1].traverse(this, scope);
        if (isClosingGenericToken()) {
          this.scribe.printNextToken(CLOSING_GENERICS_EXPECTEDTOKENS, this.preferences.insert_space_before_closing_angle_bracket_in_type_arguments);
        }
        if (this.preferences.insert_space_after_closing_angle_bracket_in_type_arguments) {
          this.scribe.space();
        }
    } else {
      this.scribe.space();
    }

    allocationExpression.type.traverse(this, scope);
   
    this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_method_invocation);

    final Expression[] arguments = allocationExpression.arguments;
    if (arguments != null) {
      if (this.preferences.insert_space_after_opening_paren_in_method_invocation) {
        this.scribe.space();
      }     
      int argumentLength = arguments.length;
      Alignment argumentsAlignment =this.scribe.createAlignment(
          "allocation",//$NON-NLS-1$
          this.preferences.alignment_for_arguments_in_allocation_expression,
          argumentLength,
          this.scribe.scanner.currentPosition);
      this.scribe.enterAlignment(argumentsAlignment);
      boolean ok = false;
      do {
        try {
          for (int i = 0; i < argumentLength; i++) {
            if (i > 0) {
              this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_allocation_expression);
              this.scribe.printTrailingComment();
            }
            this.scribe.alignFragment(argumentsAlignment, i);
            if (i > 0 && this.preferences.insert_space_after_comma_in_allocation_expression) {
              this.scribe.space();
            }
            arguments[i].traverse(this, scope);
          }
          ok = true;
        } catch (AlignmentException e) {
          this.scribe.redoAlignment(e);
        }
      } while (!ok);
      this.scribe.exitAlignment(argumentsAlignment, true);
      this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_method_invocation);
    } else {
      this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_between_empty_parens_in_method_invocation);
    }
   
    if (numberOfParens > 0) {
      manageClosingParenthesizedExpression(allocationExpression, numberOfParens);
    }
    return false;
  }

  /**
   * @see org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.aspectj.org.eclipse.jdt.internal.compiler.ast.AND_AND_Expression, org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope)
   */
  public boolean visit(
    AND_AND_Expression and_and_Expression,
    BlockScope scope) {
     
    return dumpBinaryExpression(and_and_Expression, TerminalTokens.TokenNameAND_AND, scope);
  }
  public boolean visit(
      AnnotationMethodDeclaration annotationTypeMemberDeclaration,
      ClassScope scope) {       
        /*
         * Print comments to get proper line number
         */
        this.scribe.printComment();       
        this.scribe.printModifiers(annotationTypeMemberDeclaration.annotations, this);
    this.scribe.space();
    /*
     * Print the method return type
     */ 
    final TypeReference returnType = annotationTypeMemberDeclaration.returnType;
    final MethodScope annotationTypeMemberDeclarationScope = annotationTypeMemberDeclaration.scope;
   
    if (returnType != null) {
      returnType.traverse(this, annotationTypeMemberDeclarationScope);
    }
    /*
     * Print the method name
     */
    this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, true);
    this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_annotation_type_member_declaration);
    this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_between_empty_parens_in_annotation_type_member_declaration);

    /*
     * Check for extra dimensions
     */
    int extraDimensions = annotationTypeMemberDeclaration.extendedDimensions;
    if (extraDimensions != 0) {
       for (int i = 0; i < extraDimensions; i++) {
         this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET);
         this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET);
       }
    }

    Expression defaultValue = annotationTypeMemberDeclaration.defaultValue;
    if (defaultValue != null) {
      this.scribe.printNextToken(TerminalTokens.TokenNamedefault, true);
      this.scribe.space();
      defaultValue.traverse(this, (BlockScope) null);
    }
    this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
    this.scribe.printTrailingComment();
    return false;
  }

  /**
   * @see org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.aspectj.org.eclipse.jdt.internal.compiler.ast.Argument, org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope)
   */
  public boolean visit(Argument argument, BlockScope scope) {

    if (argument.modifiers != NO_MODIFIERS || argument.annotations != null) {
          this.scribe.printComment();
      this.scribe.printModifiers(argument.annotations, this);
      this.scribe.space();
    }

    /*
     * Argument type
     */
    if (argument.type != null) {
      argument.type.traverse(this, scope);
    }
   
    if (argument.isVarArgs()) {
      this.scribe.printNextToken(TerminalTokens.TokenNameELLIPSIS, this.preferences.insert_space_before_ellipsis);
      if (this.preferences.insert_space_after_ellipsis) {
        this.scribe.space();
      }
      this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, false);
    } else {
      /*
       * Print the argument name
       */ 
      this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, true);
    }


    /*
     * Check for extra dimensions
     */
    int extraDimensions = getDimensions();
    if (extraDimensions != 0) {
       for (int i = 0; i < extraDimensions; i++) {
         this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET);
         this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET);
       }
    }
   
    return false;
  }

  /**
   * @see org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.aspectj.org.eclipse.jdt.internal.compiler.ast.ArrayAllocationExpression, org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope)
   */
  public boolean visit(
    ArrayAllocationExpression arrayAllocationExpression,
    BlockScope scope) {

      final int numberOfParens = (arrayAllocationExpression.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
      if (numberOfParens > 0) {
        manageOpeningParenthesizedExpression(arrayAllocationExpression, numberOfParens);
      }
      this.scribe.printNextToken(TerminalTokens.TokenNamenew);
      this.scribe.space();
      arrayAllocationExpression.type.traverse(this, scope);
     
      final Expression[] dimensions = arrayAllocationExpression.dimensions;
      int dimensionsLength = dimensions.length;
      for (int i = 0; i < dimensionsLength; i++) {
        if (this.preferences.insert_space_before_opening_bracket_in_array_allocation_expression) {
          this.scribe.space();
        }
        this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET, false);
        if (dimensions[i] != null) {
          if (this.preferences.insert_space_after_opening_bracket_in_array_allocation_expression) {
            this.scribe.space();
          }
          dimensions[i].traverse(this, scope);
          this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET, this.preferences.insert_space_before_closing_bracket_in_array_allocation_expression);
        } else {
          this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET, this.preferences.insert_space_between_empty_brackets_in_array_allocation_expression);
        }
      }
      final ArrayInitializer initializer = arrayAllocationExpression.initializer;
      if (initializer != null) {
        initializer.traverse(this, scope);
      }

      if (numberOfParens > 0) {
        manageClosingParenthesizedExpression(arrayAllocationExpression, numberOfParens);
      }
      return false;
  }

  /**
   * @see org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.aspectj.org.eclipse.jdt.internal.compiler.ast.ArrayInitializer, org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope)
   */
  public boolean visit(ArrayInitializer arrayInitializer, BlockScope scope) {    final int numberOfParens = (arrayInitializer.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
    if (numberOfParens > 0) {
      manageOpeningParenthesizedExpression(arrayInitializer, numberOfParens);
    }
   
    final Expression[] expressions = arrayInitializer.expressions;
    if (expressions != null) {
      String array_initializer_brace_position = this.preferences.brace_position_for_array_initializer;
      formatOpeningBrace(array_initializer_brace_position, this.preferences.insert_space_before_opening_brace_in_array_initializer);
   
      int expressionsLength = expressions.length;
      final boolean insert_new_line_after_opening_brace = this.preferences.insert_new_line_after_opening_brace_in_array_initializer;
      if (expressionsLength > 1) {
        if (insert_new_line_after_opening_brace) {
          this.scribe.printNewLine();
        }
        Alignment arrayInitializerAlignment =this.scribe.createAlignment(
            "array_initializer",//$NON-NLS-1$
            this.preferences.alignment_for_expressions_in_array_initializer,
            Alignment.R_OUTERMOST,
            expressionsLength,
            this.scribe.scanner.currentPosition,
            this.preferences.continuation_indentation_for_array_initializer,
            true);
       
        if (insert_new_line_after_opening_brace) {
            arrayInitializerAlignment.fragmentIndentations[0] = arrayInitializerAlignment.breakIndentationLevel;
        }
       
        this.scribe.enterAlignment(arrayInitializerAlignment);
        boolean ok = false;
        do {
          try {
            this.scribe.alignFragment(arrayInitializerAlignment, 0);
            if (this.preferences.insert_space_after_opening_brace_in_array_initializer) {
              this.scribe.space();
            }
            expressions[0].traverse(this, scope);
            for (int i = 1; i < expressionsLength; i++) {
              this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_array_initializer);
              this.scribe.printTrailingComment();
              this.scribe.alignFragment(arrayInitializerAlignment, i);
              if (this.preferences.insert_space_after_comma_in_array_initializer) {
                this.scribe.space();
              }
              expressions[i].traverse(this, scope);
              if (i == expressionsLength - 1) {
                if (isNextToken(TerminalTokens.TokenNameCOMMA)) {
                  this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_array_initializer);
                  this.scribe.printTrailingComment();
                }
              }
            }
            ok = true;
          } catch (AlignmentException e) {
            this.scribe.redoAlignment(e);
          }
        } while (!ok);
        this.scribe.exitAlignment(arrayInitializerAlignment, true);
      } else {
        if (insert_new_line_after_opening_brace) {
          this.scribe.printNewLine();
          this.scribe.indent();
        }
        // we don't need to use an alignment
        if (this.preferences.insert_space_after_opening_brace_in_array_initializer) {
          this.scribe.space();
        } else {
          this.scribe.needSpace = false;
        }
        expressions[0].traverse(this, scope);
        if (isNextToken(TerminalTokens.TokenNameCOMMA)) {
          this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_array_initializer);
          this.scribe.printTrailingComment();
        }
        if (insert_new_line_after_opening_brace) {
          this.scribe.unIndent();
        }
      }
      if (this.preferences.insert_new_line_before_closing_brace_in_array_initializer) {
        this.scribe.printNewLine();
      } else if (this.preferences.insert_space_before_closing_brace_in_array_initializer) {
        this.scribe.space();
      }
      this.scribe.printNextToken(TerminalTokens.TokenNameRBRACE, false);
      if (array_initializer_brace_position.equals(DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED)) {
        this.scribe.unIndent();
     
    } else {
      boolean keepEmptyArrayInitializerOnTheSameLine = this.preferences.keep_empty_array_initializer_on_one_line;
      String array_initializer_brace_position = this.preferences.brace_position_for_array_initializer;
      if (keepEmptyArrayInitializerOnTheSameLine) {
        this.scribe.printNextToken(TerminalTokens.TokenNameLBRACE, this.preferences.insert_space_before_opening_brace_in_array_initializer);
        this.scribe.printNextToken(TerminalTokens.TokenNameRBRACE, this.preferences.insert_space_between_empty_braces_in_array_initializer);
      } else {
        formatOpeningBrace(array_initializer_brace_position, this.preferences.insert_space_before_opening_brace_in_array_initializer);
        this.scribe.printNextToken(TerminalTokens.TokenNameRBRACE, false);
        if (array_initializer_brace_position.equals(DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED)) {
          this.scribe.unIndent();
        }
      }
    }
 
    if (numberOfParens > 0) {
      manageClosingParenthesizedExpression(arrayInitializer, numberOfParens);
    }
    return false;
  }
 
  /**
   * @see org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.aspectj.org.eclipse.jdt.internal.compiler.ast.ArrayQualifiedTypeReference, org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope)
   */
  public boolean visit(
    ArrayQualifiedTypeReference arrayQualifiedTypeReference,
    BlockScope scope) {

      final int numberOfParens = (arrayQualifiedTypeReference.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
      if (numberOfParens > 0) {
        manageOpeningParenthesizedExpression(arrayQualifiedTypeReference, numberOfParens);
      }
      this.scribe.printArrayQualifiedReference(arrayQualifiedTypeReference.tokens.length, arrayQualifiedTypeReference.sourceEnd);
      int dimensions = getDimensions();
      if (dimensions != 0) {
        for (int i = 0; i < dimensions; i++) {
          this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET);
          this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET);
        }
      }
      if (numberOfParens > 0) {
        manageClosingParenthesizedExpression(arrayQualifiedTypeReference, numberOfParens);
      }
      return false;
  }

  /**
   * @see org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.aspectj.org.eclipse.jdt.internal.compiler.ast.ArrayQualifiedTypeReference, org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ClassScope)
   */
  public boolean visit(
    ArrayQualifiedTypeReference arrayQualifiedTypeReference,
    ClassScope scope) {

      final int numberOfParens = (arrayQualifiedTypeReference.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
      if (numberOfParens > 0) {
        manageOpeningParenthesizedExpression(arrayQualifiedTypeReference, numberOfParens);
      }
      this.scribe.printArrayQualifiedReference(arrayQualifiedTypeReference.tokens.length, arrayQualifiedTypeReference.sourceEnd);
      int dimensions = getDimensions();
      if (dimensions != 0) {
        for (int i = 0; i < dimensions; i++) {
          this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET);
          this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET);
        }
      }
      if (numberOfParens > 0) {
        manageClosingParenthesizedExpression(arrayQualifiedTypeReference, numberOfParens);
      }
      return false;
  }


  /**
   * @see org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.aspectj.org.eclipse.jdt.internal.compiler.ast.ArrayReference, org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope)
   */
  public boolean visit(ArrayReference arrayReference, BlockScope scope) {

    final int numberOfParens = (arrayReference.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
    if (numberOfParens > 0) {
      manageOpeningParenthesizedExpression(arrayReference, numberOfParens);
    }
    arrayReference.receiver.traverse(this, scope);
    this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET, this.preferences.insert_space_before_opening_bracket_in_array_reference);
    if (this.preferences.insert_space_after_opening_bracket_in_array_reference) {
      this.scribe.space();
    }
    arrayReference.position.traverse(this, scope);
    this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET, this.preferences.insert_space_before_closing_bracket_in_array_reference);
   
    if (numberOfParens > 0) {
      manageClosingParenthesizedExpression(arrayReference, numberOfParens);
    }
    return false;
  }
 
  /**
   * @see org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.aspectj.org.eclipse.jdt.internal.compiler.ast.ArrayTypeReference, org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope)
   */
  public boolean visit(
    ArrayTypeReference arrayTypeReference,
    BlockScope scope) {

    final int numberOfParens = (arrayTypeReference.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
    if (numberOfParens > 0) {
      manageOpeningParenthesizedExpression(arrayTypeReference, numberOfParens);
    }
    this.scribe.printNextToken(SINGLETYPEREFERENCE_EXPECTEDTOKENS);
   
    int dimensions = getDimensions();
    if (dimensions != 0) {
      if (this.preferences.insert_space_before_opening_bracket_in_array_type_reference) {
        this.scribe.space();
      }
      for (int i = 0; i < dimensions; i++) {
        this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET);
        if (this.preferences.insert_space_between_brackets_in_array_type_reference) {
          this.scribe.space();
        }
        this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET);
      }
    }
    if (numberOfParens > 0) {
      manageClosingParenthesizedExpression(arrayTypeReference, numberOfParens);
    }
    return false;
  }

  /**
   * @see org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.aspectj.org.eclipse.jdt.internal.compiler.ast.ArrayTypeReference, org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ClassScope)
   */
  public boolean visit(
    ArrayTypeReference arrayTypeReference,
    ClassScope scope) {

    final int numberOfParens = (arrayTypeReference.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
    if (numberOfParens > 0) {
      manageOpeningParenthesizedExpression(arrayTypeReference, numberOfParens);
    }
    this.scribe.printNextToken(SINGLETYPEREFERENCE_EXPECTEDTOKENS);
    int dimensions = getDimensions();
    if (dimensions != 0) {
      if (this.preferences.insert_space_before_opening_bracket_in_array_type_reference) {
        this.scribe.space();
      }
      for (int i = 0; i < dimensions; i++) {
        this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET);
        if (this.preferences.insert_space_between_brackets_in_array_type_reference) {
          this.scribe.space();
        }
        this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET);
      }
    }
    if (numberOfParens > 0) {
      manageClosingParenthesizedExpression(arrayTypeReference, numberOfParens);
    }
    return false;
  }

  /**
   * @see org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.aspectj.org.eclipse.jdt.internal.compiler.ast.AssertStatement, org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope)
   */
  public boolean visit(AssertStatement assertStatement, BlockScope scope) {
   
    this.scribe.printNextToken(TerminalTokens.TokenNameassert);
    this.scribe.space();
    assertStatement.assertExpression.traverse(this, scope);
   
    if (assertStatement.exceptionArgument != null) {
      this.scribe.printNextToken(TerminalTokens.TokenNameCOLON, this.preferences.insert_space_before_colon_in_assert);
      if (this.preferences.insert_space_after_colon_in_assert) {
        this.scribe.space();
      }
      assertStatement.exceptionArgument.traverse(this, scope);
    }
    this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);   
    this.scribe.printTrailingComment();
    return false;
  }
 
  /**
   * @see org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.aspectj.org.eclipse.jdt.internal.compiler.ast.Assignment, org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope)
   */
  public boolean visit(Assignment assignment, BlockScope scope) {

    final int numberOfParens = (assignment.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
    if (numberOfParens > 0) {
      manageOpeningParenthesizedExpression(assignment, numberOfParens);
    }
    assignment.lhs.traverse(this, scope);
    this.scribe.printNextToken(TerminalTokens.TokenNameEQUAL, this.preferences.insert_space_before_assignment_operator);
    if (this.preferences.insert_space_after_assignment_operator) {
      this.scribe.space();
    }

    Alignment assignmentAlignment = this.scribe.createAlignment("assignmentAlignment", this.preferences.alignment_for_assignment, Alignment.R_OUTERMOST, 1, this.scribe.scanner.currentPosition); //$NON-NLS-1$
    this.scribe.enterAlignment(assignmentAlignment);
    boolean ok = false;
    do {
      try {
        this.scribe.alignFragment(assignmentAlignment, 0);
        assignment.expression.traverse(this, scope);
        ok = true;
      } catch(AlignmentException e){
        this.scribe.redoAlignment(e);
      }
    } while (!ok);   
    this.scribe.exitAlignment(assignmentAlignment, true);

    if (numberOfParens > 0) {
      manageClosingParenthesizedExpression(assignment, numberOfParens);
    }
    return false;
  }

  /**
   * @see org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.aspectj.org.eclipse.jdt.internal.compiler.ast.BinaryExpression, org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope)
   */
  public boolean visit(BinaryExpression binaryExpression, BlockScope scope) {

    switch((binaryExpression.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT) {
      case OperatorIds.AND :
        return dumpBinaryExpression(binaryExpression, TerminalTokens.TokenNameAND, scope);
      case OperatorIds.DIVIDE :
        return dumpBinaryExpression(binaryExpression, TerminalTokens.TokenNameDIVIDE, scope);
      case OperatorIds.GREATER :
        return dumpBinaryExpression(binaryExpression, TerminalTokens.TokenNameGREATER, scope);
      case OperatorIds.GREATER_EQUAL :
        return dumpBinaryExpression(binaryExpression, TerminalTokens.TokenNameGREATER_EQUAL, scope);
      case OperatorIds.LEFT_SHIFT :
        return dumpBinaryExpression(binaryExpression, TerminalTokens.TokenNameLEFT_SHIFT, scope);
      case OperatorIds.LESS :
        return dumpBinaryExpression(binaryExpression, TerminalTokens.TokenNameLESS, scope);
      case OperatorIds.LESS_EQUAL :
        return dumpBinaryExpression(binaryExpression, TerminalTokens.TokenNameLESS_EQUAL, scope);
      case OperatorIds.MINUS :
        return dumpBinaryExpression(binaryExpression, TerminalTokens.TokenNameMINUS, scope);
      case OperatorIds.MULTIPLY :
        return dumpBinaryExpression(binaryExpression, TerminalTokens.TokenNameMULTIPLY, scope);
      case OperatorIds.OR :
        return dumpBinaryExpression(binaryExpression, TerminalTokens.TokenNameOR, scope);
      case OperatorIds.PLUS :
        return dumpBinaryExpression(binaryExpression, TerminalTokens.TokenNamePLUS, scope);
      case OperatorIds.REMAINDER :
        return dumpBinaryExpression(binaryExpression, TerminalTokens.TokenNameREMAINDER, scope);
      case OperatorIds.RIGHT_SHIFT :
        return dumpBinaryExpression(binaryExpression, TerminalTokens.TokenNameRIGHT_SHIFT, scope);
      case OperatorIds.UNSIGNED_RIGHT_SHIFT :
        return dumpBinaryExpression(binaryExpression, TerminalTokens.TokenNameUNSIGNED_RIGHT_SHIFT, scope);
      case OperatorIds.XOR :
        return dumpBinaryExpression(binaryExpression, TerminalTokens.TokenNameXOR, scope);
      default:
        throw new IllegalStateException();
    }
  }
 
  /**
   * @see org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.aspectj.org.eclipse.jdt.internal.compiler.ast.Block, org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope)
   */
  public boolean visit(Block block, BlockScope scope) {
    formatBlock(block, scope, this.preferences.brace_position_for_block, this.preferences.insert_space_before_opening_brace_in_block)
    return false;
  }

  /**
   * @see org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.aspectj.org.eclipse.jdt.internal.compiler.ast.BreakStatement, org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope)
   */
  public boolean visit(BreakStatement breakStatement, BlockScope scope) {
   
    this.scribe.printNextToken(TerminalTokens.TokenNamebreak);
    if (breakStatement.label != null) {
      this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, true);
    }
    this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
    this.scribe.printTrailingComment();
    return false;
  }

  /**
   * @see org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.aspectj.org.eclipse.jdt.internal.compiler.ast.CaseStatement, org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope)
   */
  public boolean visit(CaseStatement caseStatement, BlockScope scope) {   
    if (caseStatement.constantExpression == null) {
      this.scribe.printNextToken(TerminalTokens.TokenNamedefault);
      this.scribe.printNextToken(TerminalTokens.TokenNameCOLON, this.preferences.insert_space_before_colon_in_default);
    } else {
      this.scribe.printNextToken(TerminalTokens.TokenNamecase);
      this.scribe.space();
      caseStatement.constantExpression.traverse(this, scope);
      this.scribe.printNextToken(TerminalTokens.TokenNameCOLON, this.preferences.insert_space_before_colon_in_case);
    }
    return false;
  }



  /**
   * @see org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.aspectj.org.eclipse.jdt.internal.compiler.ast.CastExpression, org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope)
   */
  public boolean visit(CastExpression castExpression, BlockScope scope) {

    final int numberOfParens = (castExpression.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
    if (numberOfParens > 0) {
      manageOpeningParenthesizedExpression(castExpression, numberOfParens);
    }
    this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN);
    if (this.preferences.insert_space_after_opening_paren_in_cast) {
      this.scribe.space();
    }
    castExpression.type.traverse(this, scope);

    this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_cast);
    if (this.preferences.insert_space_after_closing_paren_in_cast) {
      this.scribe.space();
    }
    castExpression.expression.traverse(this, scope);
   
    if (numberOfParens > 0) {
      manageClosingParenthesizedExpression(castExpression, numberOfParens);
    }
    return false;
  }

  /**
   * @see org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.aspectj.org.eclipse.jdt.internal.compiler.ast.CharLiteral, org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope)
   */
  public boolean visit(CharLiteral charLiteral, BlockScope scope) {

    final int numberOfParens = (charLiteral.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
    if (numberOfParens > 0) {
      manageOpeningParenthesizedExpression(charLiteral, numberOfParens);
    }
    this.scribe.printNextToken(TerminalTokens.TokenNameCharacterLiteral);

    if (numberOfParens > 0) {
      manageClosingParenthesizedExpression(charLiteral, numberOfParens);
    }
    return false;
  }


  /**
   * @see org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.aspectj.org.eclipse.jdt.internal.compiler.ast.ClassLiteralAccess, org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope)
   */
  public boolean visit(ClassLiteralAccess classLiteral, BlockScope scope) {

    final int numberOfParens = (classLiteral.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
    if (numberOfParens > 0) {
      manageOpeningParenthesizedExpression(classLiteral, numberOfParens);
    }
    classLiteral.type.traverse(this, scope);
    this.scribe.printNextToken(TerminalTokens.TokenNameDOT);
    this.scribe.printNextToken(TerminalTokens.TokenNameclass);
   
    if (numberOfParens > 0) {
      manageClosingParenthesizedExpression(classLiteral, numberOfParens);
    }
    return false;
  }

  /**
   * @see org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.aspectj.org.eclipse.jdt.internal.compiler.ast.Clinit, org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ClassScope)
   */
  public boolean visit(Clinit clinit, ClassScope scope) {

    return false;
  }
 
  /**
   * @see org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.aspectj.org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration, org.aspectj.org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope)
   */
  public boolean visit(
    CompilationUnitDeclaration compilationUnitDeclaration,
    CompilationUnitScope scope) {
   
    // fake new line to handle empty lines before package declaration or import declarations
    this.scribe.lastNumberOfNewLines = 1;
    /*
     * Package declaration
     */
    final boolean hasPackage = compilationUnitDeclaration.currentPackage != null;
    if (hasPackage) {
      if (hasComments()) {
        this.scribe.printComment();
      }
      int blankLinesBeforePackage = this.preferences.blank_lines_before_package;
      if (blankLinesBeforePackage > 0) {
        this.scribe.printEmptyLines(blankLinesBeforePackage);
      }

      this.scribe.printModifiers(compilationUnitDeclaration.currentPackage.annotations, this);
      this.scribe.space();
      // dump the package keyword
      this.scribe.printNextToken(TerminalTokens.TokenNamepackage);
      this.scribe.space();
      this.scribe.printQualifiedReference(compilationUnitDeclaration.currentPackage.sourceEnd);
      this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
      this.scribe.printTrailingComment();
      int blankLinesAfterPackage = this.preferences.blank_lines_after_package;
      if (blankLinesAfterPackage > 0) {
        this.scribe.printEmptyLines(blankLinesAfterPackage);
      } else {
        this.scribe.printNewLine();
      }     
    } else {
      this.scribe.printComment();
    }
   
    /*
     * Import statements
     */
    final ImportReference[] imports = compilationUnitDeclaration.imports;
    if (imports != null) {
      if (hasPackage) {
        int blankLinesBeforeImports = this.preferences.blank_lines_before_imports;
        if (blankLinesBeforeImports > 0) {
          this.scribe.printEmptyLines(blankLinesBeforeImports);
        }
      }
      int importLength = imports.length;
      int savedNumberOfLineToPreserve = this.preferences.number_of_empty_lines_to_preserve;
      if (importLength != 1) {
        format(imports[0], false);
          for (int i = 1; i < importLength - 1; i++) {
            format(imports[i], false);
          }
          format(imports[importLength - 1], true);
          this.preferences.number_of_empty_lines_to_preserve = savedNumberOfLineToPreserve;
      } else {
        format(imports[0], true);
      }
      this.preferences.number_of_empty_lines_to_preserve = savedNumberOfLineToPreserve;
     
      int blankLinesAfterImports = this.preferences.blank_lines_after_imports;
      if (blankLinesAfterImports > 0) {
        this.scribe.printEmptyLines(blankLinesAfterImports);
      }
    }

    formatEmptyTypeDeclaration(true);
   
    int blankLineBetweenTypeDeclarations = this.preferences.blank_lines_between_type_declarations;
    /*
     * Type declarations
     */
    final TypeDeclaration[] types = compilationUnitDeclaration.types;
    if (types != null) {
      int typesLength = types.length;
      for (int i = 0; i < typesLength - 1; i++) {
        types[i].traverse(this, scope);
        formatEmptyTypeDeclaration(false);
        if (blankLineBetweenTypeDeclarations != 0) {
          this.scribe.printEmptyLines(blankLineBetweenTypeDeclarations);
        } else {
          this.scribe.printNewLine();
        }
      }
      types[typesLength - 1].traverse(this, scope);
    }
    this.scribe.printEndOfCompilationUnit();
    return false;
  }

  /**
   * @see org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.aspectj.org.eclipse.jdt.internal.compiler.ast.CompoundAssignment, org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope)
   */
  public boolean visit(
    CompoundAssignment compoundAssignment,
    BlockScope scope) {
     
    final int numberOfParens = (compoundAssignment.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
    if (numberOfParens > 0) {
      manageOpeningParenthesizedExpression(compoundAssignment, numberOfParens);
    }
    compoundAssignment.lhs.traverse(this, scope);
   
    /*
     * Print the operator
     */
    int operator;
    switch(compoundAssignment.operator) {
      case OperatorIds.PLUS :
        operator = TerminalTokens.TokenNamePLUS_EQUAL;
        break;
      case OperatorIds.MINUS :
        operator = TerminalTokens.TokenNameMINUS_EQUAL;
        break;
      case OperatorIds.MULTIPLY :
        operator = TerminalTokens.TokenNameMULTIPLY_EQUAL;
        break;
      case OperatorIds.DIVIDE :
        operator = TerminalTokens.TokenNameDIVIDE_EQUAL;
        break;
      case OperatorIds.AND :
        operator = TerminalTokens.TokenNameAND_EQUAL;
        break;
      case OperatorIds.OR :
        operator = TerminalTokens.TokenNameOR_EQUAL;
        break;
      case OperatorIds.XOR :
        operator = TerminalTokens.TokenNameXOR_EQUAL;
        break;
      case OperatorIds.REMAINDER :
        operator = TerminalTokens.TokenNameREMAINDER_EQUAL;
        break;
      case OperatorIds.LEFT_SHIFT :
        operator = TerminalTokens.TokenNameLEFT_SHIFT_EQUAL;
        break;
      case OperatorIds.RIGHT_SHIFT :
        operator = TerminalTokens.TokenNameRIGHT_SHIFT_EQUAL;
        break;
      default: // OperatorIds.UNSIGNED_RIGHT_SHIFT :
        operator = TerminalTokens.TokenNameUNSIGNED_RIGHT_SHIFT_EQUAL;
    }
   
    this.scribe.printNextToken(operator, this.preferences.insert_space_before_assignment_operator);
    if (this.preferences.insert_space_after_assignment_operator) {
      this.scribe.space();
    }
    Alignment assignmentAlignment = this.scribe.createAlignment("compoundAssignmentAlignment", this.preferences.alignment_for_assignment, Alignment.R_OUTERMOST, 1, this.scribe.scanner.currentPosition); //$NON-NLS-1$
    this.scribe.enterAlignment(assignmentAlignment);
    boolean ok = false;
    do {
      try {
        this.scribe.alignFragment(assignmentAlignment, 0);
        compoundAssignment.expression.traverse(this, scope);
        ok = true;
      } catch(AlignmentException e){
        this.scribe.redoAlignment(e);
      }
    } while (!ok);   
    this.scribe.exitAlignment(assignmentAlignment, true);
   
    if (numberOfParens > 0) {
      manageClosingParenthesizedExpression(compoundAssignment, numberOfParens);
    }
    return false;
  }

  /**
     * @see org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.aspectj.org.eclipse.jdt.internal.compiler.ast.ConditionalExpression, org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope)
     */
    public boolean visit(
      ConditionalExpression conditionalExpression,
      BlockScope scope) {
   
      final int numberOfParens = (conditionalExpression.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
      if (numberOfParens > 0) {
        manageOpeningParenthesizedExpression(conditionalExpression, numberOfParens);
      }
      conditionalExpression.condition.traverse(this, scope);
   
      Alignment conditionalExpressionAlignment =this.scribe.createAlignment(
          "conditionalExpression", //$NON-NLS-1$
          this.preferences.alignment_for_conditional_expression,
          2,
          this.scribe.scanner.currentPosition);
   
      this.scribe.enterAlignment(conditionalExpressionAlignment);
      boolean ok = false;
      do {
        try {
          this.scribe.alignFragment(conditionalExpressionAlignment, 0);
          this.scribe.printNextToken(TerminalTokens.TokenNameQUESTION, this.preferences.insert_space_before_question_in_conditional);
   
          if (this.preferences.insert_space_after_question_in_conditional) {
            this.scribe.space();
          }
          conditionalExpression.valueIfTrue.traverse(this, scope);
          this.scribe.printTrailingComment();
          this.scribe.alignFragment(conditionalExpressionAlignment, 1);
          this.scribe.printNextToken(TerminalTokens.TokenNameCOLON, this.preferences.insert_space_before_colon_in_conditional);
   
          if (this.preferences.insert_space_after_colon_in_conditional) {
            this.scribe.space();
          }
          conditionalExpression.valueIfFalse.traverse(this, scope);
   
          ok = true;
        } catch (AlignmentException e) {
          this.scribe.redoAlignment(e);
        }
      } while (!ok);
      this.scribe.exitAlignment(conditionalExpressionAlignment, true);
       
      if (numberOfParens > 0) {
        manageClosingParenthesizedExpression(conditionalExpression, numberOfParens);
      }
      return false
    }


  /**
   * @see org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.aspectj.org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration, org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ClassScope)
   */
  public boolean visit(
    ConstructorDeclaration constructorDeclaration,
    ClassScope scope) {
     
    if (constructorDeclaration.ignoreFurtherInvestigation) {
      this.scribe.printComment();
      if (this.scribe.indentationLevel != 0) {
        this.scribe.printIndentationIfNecessary();
      }
      this.scribe.scanner.resetTo(constructorDeclaration.declarationSourceEnd + 1, this.scribe.scannerEndPosition - 1);
      this.scribe.printTrailingComment();
      switch(this.scribe.scanner.source[this.scribe.scanner.currentPosition]) {
        case '\n' :
          this.scribe.scanner.currentPosition++;
          this.scribe.lastNumberOfNewLines = 1;
          break;
        case '\r' :
          this.scribe.scanner.currentPosition++;
          if (this.scribe.scanner.source[this.scribe.scanner.currentPosition] == '\n') {
            this.scribe.scanner.currentPosition++;
          }
          this.scribe.lastNumberOfNewLines = 1;
      }
      return false;
    }
        /*
         * Print comments to get proper line number
         */
        this.scribe.printComment();
        int line = this.scribe.line;
    this.scribe.printModifiers(constructorDeclaration.annotations, this);
    if (this.scribe.line > line) {
          // annotations introduced new line, but this is not a line wrapping
      // see 158267
      line = this.scribe.line;
    }
    this.scribe.space();

    TypeParameter[] typeParameters = constructorDeclaration.typeParameters;
    if (typeParameters != null) {
      this.scribe.printNextToken(TerminalTokens.TokenNameLESS, this.preferences.insert_space_before_opening_angle_bracket_in_type_parameters);
      if (this.preferences.insert_space_after_opening_angle_bracket_in_type_parameters) {
        this.scribe.space();
      }
      int length = typeParameters.length;
      for (int i = 0; i < length - 1; i++) {
        typeParameters[i].traverse(this, constructorDeclaration.scope);
        this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_type_parameters);
        if (this.preferences.insert_space_after_comma_in_type_parameters) {
          this.scribe.space();
        }       
      }
      typeParameters[length - 1].traverse(this, constructorDeclaration.scope);
      if (isClosingGenericToken()) {
        this.scribe.printNextToken(CLOSING_GENERICS_EXPECTEDTOKENS, this.preferences.insert_space_before_closing_angle_bracket_in_type_parameters);
      }
      if (this.preferences.insert_space_after_closing_angle_bracket_in_type_parameters) {
        this.scribe.space();
      }
    }

    /*
     * Print the method name
     */ 
    this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, true);

    formatMethodArguments(
      constructorDeclaration,
      this.preferences.insert_space_before_opening_paren_in_constructor_declaration,
      this.preferences.insert_space_between_empty_parens_in_constructor_declaration,
      this.preferences.insert_space_before_closing_paren_in_constructor_declaration,
      this.preferences.insert_space_after_opening_paren_in_constructor_declaration,
      this.preferences.insert_space_before_comma_in_constructor_declaration_parameters,
      this.preferences.insert_space_after_comma_in_constructor_declaration_parameters,
      this.preferences.alignment_for_parameters_in_constructor_declaration);

    formatThrowsClause(
        constructorDeclaration,
        this.preferences.insert_space_before_comma_in_constructor_declaration_throws,
        this.preferences.insert_space_after_comma_in_constructor_declaration_throws,
        this.preferences.alignment_for_throws_clause_in_constructor_declaration);

    if (!constructorDeclaration.isNative() && !constructorDeclaration.isAbstract()) {
      /*
       * Method body
       */
      String constructor_declaration_brace = this.preferences.brace_position_for_constructor_declaration;
      formatLeftCurlyBrace(line, constructor_declaration_brace);
      formatOpeningBrace(constructor_declaration_brace, this.preferences.insert_space_before_opening_brace_in_constructor_declaration);
      final int numberOfBlankLinesAtBeginningOfMethodBody = this.preferences.blank_lines_at_beginning_of_method_body;
      if (numberOfBlankLinesAtBeginningOfMethodBody > 0) {
        this.scribe.printEmptyLines(numberOfBlankLinesAtBeginningOfMethodBody);
      }
      if (constructorDeclaration.constructorCall != null && !constructorDeclaration.constructorCall.isImplicitSuper()) {
        this.scribe.printNewLine();
        if (this.preferences.indent_statements_compare_to_body) {
          this.scribe.indent();
        }
        constructorDeclaration.constructorCall.traverse(this, constructorDeclaration.scope);
        if (this.preferences.indent_statements_compare_to_body) {
          this.scribe.unIndent();
        }
      }
      final Statement[] statements = constructorDeclaration.statements;
      if (statements != null) {
        this.scribe.printNewLine();
        if (this.preferences.indent_statements_compare_to_body) {
          this.scribe.indent();
        }
        formatStatements(constructorDeclaration.scope, statements, true);
        this.scribe.printComment();
        if (this.preferences.indent_statements_compare_to_body) {
          this.scribe.unIndent();
        }
      } else if (this.preferences.insert_new_line_in_empty_method_body) {
        this.scribe.printNewLine();
        if (this.preferences.indent_statements_compare_to_body) {
          this.scribe.indent();
        }
        this.scribe.printComment();
        if (this.preferences.indent_statements_compare_to_body) {
          this.scribe.unIndent();
        }
      }
      this.scribe.printNextToken(TerminalTokens.TokenNameRBRACE);
      this.scribe.printTrailingComment();
      if (constructor_declaration_brace.equals(DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED)) {
        this.scribe.unIndent();
      }
    } else {
      // no method body
      this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
      this.scribe.printTrailingComment();
    }
    return false;
  }

  /**
   * @see org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.aspectj.org.eclipse.jdt.internal.compiler.ast.ContinueStatement, org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope)
   */
  public boolean visit(ContinueStatement continueStatement, BlockScope scope) {

    this.scribe.printNextToken(TerminalTokens.TokenNamecontinue);
    if (continueStatement.label != null) {
      this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, true);
    }
    this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
    this.scribe.printTrailingComment();
    return false;
  }


  /**
   * @see org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.aspectj.org.eclipse.jdt.internal.compiler.ast.DoStatement, org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope)
   */
  public boolean visit(DoStatement doStatement, BlockScope scope) {

    this.scribe.printNextToken(TerminalTokens.TokenNamedo);
    final int line = this.scribe.line;
   
    final Statement action = doStatement.action;
    if (action != null) {
      if (action instanceof Block) {
        formatLeftCurlyBrace(line, this.preferences.brace_position_for_block);
        action.traverse(this, scope);
      } else if (action instanceof EmptyStatement) {
        /*
         * This is an empty statement
         */
        formatNecessaryEmptyStatement();
      } else {
        this.scribe.printNewLine();
        this.scribe.indent();
        action.traverse(this, scope);
        if (action instanceof Expression) {
          this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
          this.scribe.printTrailingComment();
        }
        this.scribe.printNewLine();
        this.scribe.unIndent();
      }
    } else {
      /*
       * This is an empty statement
       */
      formatNecessaryEmptyStatement();
    }
   
    if (this.preferences.insert_new_line_before_while_in_do_statement) {
      this.scribe.printNewLine();
    }
    this.scribe.printNextToken(TerminalTokens.TokenNamewhile, this.preferences.insert_space_after_closing_brace_in_block);
    this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_while);
   
    if (this.preferences.insert_space_after_opening_paren_in_while) {
      this.scribe.space();
    }
   
    doStatement.condition.traverse(this, scope);
   
    this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_while);
    this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
    this.scribe.printTrailingComment();
    return false;
  }

  /**
   * @see org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.aspectj.org.eclipse.jdt.internal.compiler.ast.DoubleLiteral, org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope)
   */
  public boolean visit(DoubleLiteral doubleLiteral, BlockScope scope) {

    final int numberOfParens = (doubleLiteral.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
    if (numberOfParens > 0) {
      manageOpeningParenthesizedExpression(doubleLiteral, numberOfParens);
    }
    Constant constant = doubleLiteral.constant;
    if (constant != null && constant.doubleValue() < 0) {
      this.scribe.printNextToken(TerminalTokens.TokenNameMINUS);     
    }
    this.scribe.printNextToken(TerminalTokens.TokenNameDoubleLiteral);

    if (numberOfParens > 0) {
      manageClosingParenthesizedExpression(doubleLiteral, numberOfParens);
    }
    return false;
  }

  /**
   * @see org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.aspectj.org.eclipse.jdt.internal.compiler.ast.EmptyStatement, org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope)
   */
  public boolean visit(EmptyStatement statement, BlockScope scope) {
    if (this.preferences.put_empty_statement_on_new_line) {
      this.scribe.printNewLine();
    }
    this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
    this.scribe.printTrailingComment();
    return false
  }
  // field is an enum constant
  public boolean visit(FieldDeclaration enumConstant, MethodScope scope) {
        /*
         * Print comments to get proper line number
         */
        this.scribe.printComment();
        final int line = this.scribe.line;
       
        this.scribe.printModifiers(enumConstant.annotations, this);
    this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, false);
    formatEnumConstantArguments(
      enumConstant,
      this.preferences.insert_space_before_opening_paren_in_enum_constant,
      this.preferences.insert_space_between_empty_parens_in_enum_constant,
      this.preferences.insert_space_before_closing_paren_in_enum_constant,
      this.preferences.insert_space_after_opening_paren_in_enum_constant,
      this.preferences.insert_space_before_comma_in_enum_constant_arguments,
      this.preferences.insert_space_after_comma_in_enum_constant_arguments,
      this.preferences.alignment_for_arguments_in_enum_constant);     
   
    Expression initialization = enumConstant.initialization;
    if (initialization instanceof QualifiedAllocationExpression) {
      TypeDeclaration typeDeclaration = ((QualifiedAllocationExpression) initialization).anonymousType;
      int fieldsCount = typeDeclaration.fields == null ? 0 : typeDeclaration.fields.length;
      int methodsCount = typeDeclaration.methods == null ? 0 : typeDeclaration.methods.length;
      int membersCount = typeDeclaration.memberTypes == null ? 0 : typeDeclaration.memberTypes.length;
     
      /*
       * Type body
       */
      String enum_constant_brace = this.preferences.brace_position_for_enum_constant;
 
          formatLeftCurlyBrace(line, enum_constant_brace);
      formatTypeOpeningBraceForEnumConstant(enum_constant_brace, this.preferences.insert_space_before_opening_brace_in_enum_constant, typeDeclaration);
     
      if (this.preferences.indent_body_declarations_compare_to_enum_constant_header) {
        this.scribe.indent();
      }
 
      if (fieldsCount != 0 || methodsCount != 0 || membersCount != 0) {
        formatTypeMembers(typeDeclaration);
      }

      if (this.preferences.indent_body_declarations_compare_to_enum_constant_header) {
        this.scribe.unIndent();
      }
     
      if (this.preferences.insert_new_line_in_empty_enum_constant) {
        this.scribe.printNewLine();
      }
      this.scribe.printNextToken(TerminalTokens.TokenNameRBRACE);
      this.scribe.printTrailingComment();
      if (enum_constant_brace.equals(DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED)) {
        this.scribe.unIndent();
      }
      if (hasComments()) {
        this.scribe.printNewLine();
      }
    }
    return false;
  }
  /**
   * @see org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.aspectj.org.eclipse.jdt.internal.compiler.ast.EqualExpression, org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope)
   */
  public boolean visit(EqualExpression equalExpression, BlockScope scope) {

    if ((equalExpression.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT == OperatorIds.EQUAL_EQUAL) {
      return dumpEqualityExpression(equalExpression, TerminalTokens.TokenNameEQUAL_EQUAL, scope);
    } else {
      return dumpEqualityExpression(equalExpression, TerminalTokens.TokenNameNOT_EQUAL, scope);
    }     
  }

  /**
   * @see org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.aspectj.org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall, org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope)
   */
  public boolean visit(
    ExplicitConstructorCall explicitConstructor,
    BlockScope scope) {

    if (explicitConstructor.isImplicitSuper()) {
      return false;
    }
    final Expression qualification = explicitConstructor.qualification;
    if (qualification != null) {
      qualification.traverse(this, scope);
      this.scribe.printNextToken(TerminalTokens.TokenNameDOT);
    }

    TypeReference[] typeArguments = explicitConstructor.typeArguments;
    if (typeArguments != null) {
        this.scribe.printNextToken(TerminalTokens.TokenNameLESS, this.preferences.insert_space_before_opening_angle_bracket_in_type_arguments);
        if (this.preferences.insert_space_after_opening_angle_bracket_in_type_arguments) {
          this.scribe.space();
        }
        int length = typeArguments.length;
        for (int i = 0; i < length - 1; i++) {
          typeArguments[i].traverse(this, scope);
          this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_type_arguments);
          if (this.preferences.insert_space_after_comma_in_type_arguments) {
            this.scribe.space();
          }       
        }
        typeArguments[length - 1].traverse(this, scope);
        if (isClosingGenericToken()) {
          this.scribe.printNextToken(CLOSING_GENERICS_EXPECTEDTOKENS, this.preferences.insert_space_before_closing_angle_bracket_in_type_arguments);
        }
        if (this.preferences.insert_space_after_closing_angle_bracket_in_type_arguments) {
          this.scribe.space();
        }
    }
   
    if (explicitConstructor.isSuperAccess()) {
      this.scribe.printNextToken(TerminalTokens.TokenNamesuper);
    } else {
      this.scribe.printNextToken(TerminalTokens.TokenNamethis);
    }
    this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_method_invocation);
   
    final Expression[] arguments = explicitConstructor.arguments;
    if (arguments != null) {
      if (this.preferences.insert_space_after_opening_paren_in_method_invocation) {
        this.scribe.space();
      }
      int argumentLength = arguments.length;
      Alignment argumentsAlignment =this.scribe.createAlignment(
          "explicit_constructor_call",//$NON-NLS-1$
          this.preferences.alignment_for_arguments_in_explicit_constructor_call,
          argumentLength,
          this.scribe.scanner.currentPosition);
      this.scribe.enterAlignment(argumentsAlignment);
      boolean ok = false;
      do {
        try {
          for (int i = 0; i < argumentLength; i++) {
            if (i > 0) {
              this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_explicit_constructor_call_arguments);
              this.scribe.printTrailingComment();
            }
            this.scribe.alignFragment(argumentsAlignment, i);
            if (i > 0 && this.preferences.insert_space_after_comma_in_explicit_constructor_call_arguments) {
              this.scribe.space();
            }
            arguments[i].traverse(this, scope);
          }
          ok = true;
        } catch (AlignmentException e) {
          this.scribe.redoAlignment(e);
        }
      } while (!ok);
      this.scribe.exitAlignment(argumentsAlignment, true);
      this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_method_invocation);
    } else {
      this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_between_empty_parens_in_method_invocation);
    }
    this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
    this.scribe.printTrailingComment();
    return false;
  }
  /**
   * @see org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.aspectj.org.eclipse.jdt.internal.compiler.ast.FalseLiteral, org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope)
   */
  public boolean visit(FalseLiteral falseLiteral, BlockScope scope) {

    final int numberOfParens = (falseLiteral.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
    if (numberOfParens > 0) {
      manageOpeningParenthesizedExpression(falseLiteral, numberOfParens);
    }
    this.scribe.printNextToken(TerminalTokens.TokenNamefalse);

    if (numberOfParens > 0) {
      manageClosingParenthesizedExpression(falseLiteral, numberOfParens);
    }
    return false;
  }
  /**
   * @see org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.aspectj.org.eclipse.jdt.internal.compiler.ast.FieldReference, org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope)
   */
  public boolean visit(FieldReference fieldReference, BlockScope scope) {

    final int numberOfParens = (fieldReference.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
    if (numberOfParens > 0) {
      manageOpeningParenthesizedExpression(fieldReference, numberOfParens);
    }
    fieldReference.receiver.traverse(this, scope);
    this.scribe.printNextToken(TerminalTokens.TokenNameDOT);
    this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier);
   
    if (numberOfParens > 0) {
      manageClosingParenthesizedExpression(fieldReference, numberOfParens);
    }
    return false;
  }

  /**
   * @see org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.aspectj.org.eclipse.jdt.internal.compiler.ast.FloatLiteral, org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope)
   */
  public boolean visit(FloatLiteral floatLiteral, BlockScope scope) {

    final int numberOfParens = (floatLiteral.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
    if (numberOfParens > 0) {
      manageOpeningParenthesizedExpression(floatLiteral, numberOfParens);
    }
    Constant constant = floatLiteral.constant;
    if (constant != null && floatLiteral.constant.floatValue() < 0) {
      this.scribe.printNextToken(TerminalTokens.TokenNameMINUS);     
    }
    this.scribe.printNextToken(TerminalTokens.TokenNameFloatingPointLiteral);

    if (numberOfParens > 0) {
      manageClosingParenthesizedExpression(floatLiteral, numberOfParens);
    }
    return false;
  }
  public boolean visit(ForeachStatement forStatement, BlockScope scope) {
    this.scribe.printNextToken(TerminalTokens.TokenNamefor);
      final int line = this.scribe.line;
      this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_for);
   
    if (this.preferences.insert_space_after_opening_paren_in_for) {
      this.scribe.space();
    }
    formatLocalDeclaration(forStatement.elementVariable, scope, false, false);

    this.scribe.printNextToken(TerminalTokens.TokenNameCOLON, this.preferences.insert_space_before_colon_in_for);
    if (this.preferences.insert_space_after_colon_in_for) {
      this.scribe.space();
    }
    forStatement.collection.traverse(this, scope);

    this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_for);
   
    final Statement action = forStatement.action;
    if (action != null) {
      if (action instanceof Block) {
              formatLeftCurlyBrace(line, this.preferences.brace_position_for_block);
        action.traverse(this, scope);
      } else if (action instanceof EmptyStatement) {
        /*
         * This is an empty statement
         */
        formatNecessaryEmptyStatement();
      } else {
        this.scribe.indent();
        this.scribe.printNewLine();
        action.traverse(this, scope);
        this.scribe.unIndent();
      }
      if (action instanceof Expression) {
        this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
        this.scribe.printTrailingComment();
      }
    } else {
      /*
       * This is an empty statement
       */
      formatNecessaryEmptyStatement();
    }
    return false;
  }

  /**
   * @see org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.aspectj.org.eclipse.jdt.internal.compiler.ast.ForStatement, org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope)
   */
  public boolean visit(ForStatement forStatement, BlockScope scope) {
 
    this.scribe.printNextToken(TerminalTokens.TokenNamefor);
      final int line = this.scribe.line;
      this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_for);
   
    if (this.preferences.insert_space_after_opening_paren_in_for) {
      this.scribe.space();
    }
    final Statement[] initializations = forStatement.initializations;
    if (initializations != null) {
      int length = initializations.length;
      for (int i = 0; i < length; i++) {
        if (initializations[i] instanceof LocalDeclaration) {
          formatLocalDeclaration((LocalDeclaration) initializations[i], scope, this.preferences.insert_space_before_comma_in_for_inits, this.preferences.insert_space_after_comma_in_for_inits);
        } else {
          initializations[i].traverse(this, scope);
          if (i >= 0 && (i < length - 1)) {
            this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_for_inits);
            if (this.preferences.insert_space_after_comma_in_for_inits) {
              this.scribe.space();
            }
            this.scribe.printTrailingComment();
          }       
        }
      }
    }
    this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon_in_for);
    final Expression condition = forStatement.condition;
    if (condition != null) {
      if (this.preferences.insert_space_after_semicolon_in_for) {
        this.scribe.space();
      }
      condition.traverse(this, scope);
    }
    this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon_in_for);
    final Statement[] increments = forStatement.increments;
    if (increments != null) {
      if (this.preferences.insert_space_after_semicolon_in_for) {
        this.scribe.space();
      }
      for (int i = 0, length = increments.length; i < length; i++) {
        increments[i].traverse(this, scope);
        if (i != length - 1) {
          this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_for_increments);
          if (this.preferences.insert_space_after_comma_in_for_increments) {
            this.scribe.space();
          }
          this.scribe.printTrailingComment();
        }
      }
    }
    this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_for);
   
    final Statement action = forStatement.action;
    if (action != null) {
      if (action instanceof Block) {
              formatLeftCurlyBrace(line, this.preferences.brace_position_for_block);
        action.traverse(this, scope);
      } else if (action instanceof EmptyStatement) {
        /*
         * This is an empty statement
         */
        formatNecessaryEmptyStatement();
      } else {
        this.scribe.indent();
        this.scribe.printNewLine();
        action.traverse(this, scope);
        this.scribe.unIndent();
      }
      if (action instanceof Expression) {
        this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
        this.scribe.printTrailingComment();
      }
    } else {
      /*
       * This is an empty statement
       */
      formatNecessaryEmptyStatement();
    }
    return false;
  }


  /**
   * @see org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.aspectj.org.eclipse.jdt.internal.compiler.ast.IfStatement, org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope)
   */
  public boolean visit(IfStatement ifStatement, BlockScope scope) {

    this.scribe.printNextToken(TerminalTokens.TokenNameif);
        final int line = this.scribe.line;
        this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_if);
    if (this.preferences.insert_space_after_opening_paren_in_if) {
      this.scribe.space();
    }
    ifStatement.condition.traverse(this, scope);
    this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_if);

    final Statement thenStatement = ifStatement.thenStatement;
    final Statement elseStatement = ifStatement.elseStatement;

    boolean thenStatementIsBlock = false;
    if (thenStatement != null) {
      if (thenStatement instanceof Block) {
        thenStatementIsBlock = true;
        if (isGuardClause((Block)thenStatement) && elseStatement == null && this.preferences.keep_guardian_clause_on_one_line) {
          /*
           * Need a specific formatting for guard clauses
           * guard clauses are block with a single return or throw
           * statement
           */
           formatGuardClauseBlock((Block) thenStatement, scope);
        } else {
          formatLeftCurlyBrace(line, this.preferences.brace_position_for_block);
          thenStatement.traverse(this, scope);
          if (elseStatement != null && (this.preferences.insert_new_line_before_else_in_if_statement)) {
            this.scribe.printNewLine();
          }
        }
      } else if (elseStatement == null && this.preferences.keep_simple_if_on_one_line) {
        Alignment compactIfAlignment = this.scribe.createAlignment(
            "compactIf", //$NON-NLS-1$
            this.preferences.alignment_for_compact_if,
            Alignment.R_OUTERMOST,
            1,
            this.scribe.scanner.currentPosition,
            1,
            false);
        this.scribe.enterAlignment(compactIfAlignment);
        boolean ok = false;
        do {
          try {
            this.scribe.alignFragment(compactIfAlignment, 0);
            this.scribe.space();
            thenStatement.traverse(this, scope);
            if (thenStatement instanceof Expression) {
              this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
              this.scribe.printTrailingComment();
            }
            ok = true;
          } catch (AlignmentException e) {
            this.scribe.redoAlignment(e);
          }
        } while (!ok);
        this.scribe.exitAlignment(compactIfAlignment, true);
      } else if (this.preferences.keep_then_statement_on_same_line) {
        this.scribe.space();
        thenStatement.traverse(this, scope);
        if (thenStatement instanceof Expression) {
          this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
          this.scribe.printTrailingComment();
        }
        if (elseStatement != null) {
          this.scribe.printNewLine();
        }
      } else {
        this.scribe.printTrailingComment();
        this.scribe.printNewLine();
        this.scribe.indent();
        thenStatement.traverse(this, scope);
        if (thenStatement instanceof Expression) {
          this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
          this.scribe.printTrailingComment();
        }
        if (elseStatement != null) {
          this.scribe.printNewLine();
        }
        this.scribe.unIndent();
      }
    }
   
    if (elseStatement != null) {
      if (thenStatementIsBlock) {
        this.scribe.printNextToken(TerminalTokens.TokenNameelse, this.preferences.insert_space_after_closing_brace_in_block);
      } else {
        this.scribe.printNextToken(TerminalTokens.TokenNameelse, true);
      }
      if (elseStatement instanceof Block) {
        elseStatement.traverse(this, scope);
      } else if (elseStatement instanceof IfStatement) {
        if (!this.preferences.compact_else_if) {
          this.scribe.printNewLine();
          this.scribe.indent();
        }
        this.scribe.space();
        elseStatement.traverse(this, scope);
        if (!this.preferences.compact_else_if) {
          this.scribe.unIndent();
        }
      } else if (this.preferences.keep_else_statement_on_same_line) {
        this.scribe.space();
        elseStatement.traverse(this, scope);
        if (elseStatement instanceof Expression) {
          this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
          this.scribe.printTrailingComment();
        }
      } else {
        this.scribe.printNewLine();
        this.scribe.indent();
        elseStatement.traverse(this, scope);
        if (elseStatement instanceof Expression) {
          this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
          this.scribe.printTrailingComment();
        }
        this.scribe.unIndent();
      }
    }
    return false;
  }

  /**
   * @see org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.aspectj.org.eclipse.jdt.internal.compiler.ast.Initializer, org.aspectj.org.eclipse.jdt.internal.compiler.lookup.MethodScope)
   */
  public boolean visit(Initializer initializer, MethodScope scope) {

    if (initializer.isStatic()) {
      this.scribe.printNextToken(TerminalTokens.TokenNamestatic);
    }
    initializer.block.traverse(this, scope);
    return false;
  }

  /**
   * @see org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.aspectj.org.eclipse.jdt.internal.compiler.ast.InstanceOfExpression, org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope)
   */
  public boolean visit(
    InstanceOfExpression instanceOfExpression,
    BlockScope scope) {

    final int numberOfParens = (instanceOfExpression.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
    if (numberOfParens > 0) {
      manageOpeningParenthesizedExpression(instanceOfExpression, numberOfParens);
    }
    instanceOfExpression.expression.traverse(this, scope);
    this.scribe.printNextToken(TerminalTokens.TokenNameinstanceof, true);
    this.scribe.space();
    instanceOfExpression.type.traverse(this, scope);
   
    if (numberOfParens > 0) {
      manageClosingParenthesizedExpression(instanceOfExpression, numberOfParens);
    }
    return false;
  }

  /**
   * @see org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.aspectj.org.eclipse.jdt.internal.compiler.ast.IntLiteral, org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope)
   */
  public boolean visit(IntLiteral intLiteral, BlockScope scope) {

    final int numberOfParens = (intLiteral.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
    if (numberOfParens > 0) {
      manageOpeningParenthesizedExpression(intLiteral, numberOfParens);
    }
    Constant constant = intLiteral.constant;
    if (constant != null && constant.intValue() < 0) {
      this.scribe.printNextToken(TerminalTokens.TokenNameMINUS);     
    }
    this.scribe.printNextToken(TerminalTokens.TokenNameIntegerLiteral);

    if (numberOfParens > 0) {
      manageClosingParenthesizedExpression(intLiteral, numberOfParens);
    }
    return false;
  }


  /**
   * @see org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.aspectj.org.eclipse.jdt.internal.compiler.ast.LabeledStatement, org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope)
   */
  public boolean visit(LabeledStatement labeledStatement, BlockScope scope) {

    this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier);
    this.scribe.printNextToken(TerminalTokens.TokenNameCOLON, this.preferences.insert_space_before_colon_in_labeled_statement);
    if (this.preferences.insert_space_after_colon_in_labeled_statement) {
      this.scribe.space();
    }
    final Statement statement = labeledStatement.statement;
    statement.traverse(this, scope);
    if (statement instanceof Expression) {
      this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
      this.scribe.printTrailingComment();
    }
    return false;
  }

  /**
   * @see org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.aspectj.org.eclipse.jdt.internal.compiler.ast.LocalDeclaration, org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope)
   */
  public boolean visit(LocalDeclaration localDeclaration, BlockScope scope) {
    formatLocalDeclaration(localDeclaration, scope, this.preferences.insert_space_before_comma_in_multiple_local_declarations, this.preferences.insert_space_after_comma_in_multiple_local_declarations);
    return false;
  }

  /**
   * @see org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.aspectj.org.eclipse.jdt.internal.compiler.ast.LongLiteral, org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope)
   */
  public boolean visit(LongLiteral longLiteral, BlockScope scope) {

    final int numberOfParens = (longLiteral.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
    if (numberOfParens > 0) {
      manageOpeningParenthesizedExpression(longLiteral, numberOfParens);
    }
    Constant constant = longLiteral.constant;
    if (constant != null && constant.longValue() < 0) {
      this.scribe.printNextToken(TerminalTokens.TokenNameMINUS);     
    }
    this.scribe.printNextToken(TerminalTokens.TokenNameLongLiteral);

    if (numberOfParens > 0) {
      manageClosingParenthesizedExpression(longLiteral, numberOfParens);
    }
    return false;
  }
  public boolean visit(MarkerAnnotation annotation, BlockScope scope) {
    this.scribe.printNextToken(TerminalTokens.TokenNameAT);
    if (this.preferences.insert_space_after_at_in_annotation) {
      this.scribe.space();
    }
    this.scribe.printQualifiedReference(annotation.sourceEnd);
    return false;
  }
  public boolean visit(MarkerAnnotation annotation, ClassScope scope) {
    this.scribe.printNextToken(TerminalTokens.TokenNameAT);
    if (this.preferences.insert_space_after_at_in_annotation) {
      this.scribe.space();
    }
    this.scribe.printQualifiedReference(annotation.sourceEnd);
    return false;
  }
  public boolean visit(MemberValuePair pair, BlockScope scope) {
    this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier);
    this.scribe.printNextToken(TerminalTokens.TokenNameEQUAL, this.preferences.insert_space_before_assignment_operator);
    if (this.preferences.insert_space_after_assignment_operator) {
      this.scribe.space();
    }
    pair.value.traverse(this, scope)
    return false;
  }
  /**
   * @see org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.aspectj.org.eclipse.jdt.internal.compiler.ast.MessageSend, org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope)
   */
  public boolean visit(MessageSend messageSend, BlockScope scope) {

    final int numberOfParens = (messageSend.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
    if (numberOfParens > 0) {
      manageOpeningParenthesizedExpression(messageSend, numberOfParens);
    }
    CascadingMethodInvocationFragmentBuilder builder = buildFragments(messageSend, scope);
   
    if (builder.size() >= 3 && numberOfParens == 0) {
      formatCascadingMessageSends(builder, scope);
    } else {
      Alignment messageAlignment = null;
      if (!messageSend.receiver.isImplicitThis()) {
        messageSend.receiver.traverse(this, scope);
        messageAlignment = this.scribe.createAlignment(
            "messageAlignment", //$NON-NLS-1$
            this.preferences.alignment_for_selector_in_method_invocation,
            1,
            this.scribe.scanner.currentPosition);
        this.scribe.enterAlignment(messageAlignment);
        boolean ok = false;
        do {
          try {
            formatMessageSend(messageSend, scope, messageAlignment);
            ok = true;
          } catch (AlignmentException e) {
            this.scribe.redoAlignment(e);
          }
        } while (!ok);
        this.scribe.exitAlignment(messageAlignment, true);
      } else {
        formatMessageSend(messageSend, scope, null);     
      }
    }
    if (numberOfParens > 0) {
      manageClosingParenthesizedExpression(messageSend, numberOfParens);
    }
    return false;
  }

  /**
   * @see org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.aspectj.org.eclipse.jdt.internal.compiler.ast.MethodDeclaration, org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ClassScope)
   */
  public boolean visit(
    MethodDeclaration methodDeclaration,
    ClassScope scope) {

    if (methodDeclaration.ignoreFurtherInvestigation) {
      this.scribe.printComment();
      if (this.scribe.indentationLevel != 0) {
        this.scribe.printIndentationIfNecessary();
      }
      this.scribe.scanner.resetTo(methodDeclaration.declarationSourceEnd + 1, this.scribe.scannerEndPosition - 1);
      this.scribe.printTrailingComment();
      switch(this.scribe.scanner.source[this.scribe.scanner.currentPosition]) {
        case '\n' :
          this.scribe.scanner.currentPosition++;
          this.scribe.lastNumberOfNewLines = 1;
          break;
        case '\r' :
          this.scribe.scanner.currentPosition++;
          if (this.scribe.scanner.source[this.scribe.scanner.currentPosition] == '\n') {
            this.scribe.scanner.currentPosition++;
          }
          this.scribe.lastNumberOfNewLines = 1;
      }
      return false;
    }
       
        /*
         * Print comments to get proper line number
         */
        this.scribe.printComment();
        int line = this.scribe.line;
       
        this.scribe.printModifiers(methodDeclaration.annotations, this);
       
    if (this.scribe.line > line) {
          // annotations introduced new line, but this is not a line wrapping
      // see 158267
      line = this.scribe.line;
    }
    this.scribe.space();
   
    TypeParameter[] typeParameters = methodDeclaration.typeParameters;
    if (typeParameters != null) {
      this.scribe.printNextToken(TerminalTokens.TokenNameLESS, this.preferences.insert_space_before_opening_angle_bracket_in_type_parameters);
      if (this.preferences.insert_space_after_opening_angle_bracket_in_type_parameters) {
        this.scribe.space();
      }
      int length = typeParameters.length;
      for (int i = 0; i < length - 1; i++) {
        typeParameters[i].traverse(this, methodDeclaration.scope);
        this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_type_parameters);
        if (this.preferences.insert_space_after_comma_in_type_parameters) {
          this.scribe.space();
        }       
      }
      typeParameters[length - 1].traverse(this, methodDeclaration.scope);
      if (isClosingGenericToken()) {
        this.scribe.printNextToken(CLOSING_GENERICS_EXPECTEDTOKENS, this.preferences.insert_space_before_closing_angle_bracket_in_type_parameters);
      }
      if (this.preferences.insert_space_after_closing_angle_bracket_in_type_parameters) {
        this.scribe.space();
      }
    }
   
    /*
     * Print the method return type
     */ 
    final TypeReference returnType = methodDeclaration.returnType;
    final MethodScope methodDeclarationScope = methodDeclaration.scope;
   
    if (returnType != null) {
      returnType.traverse(this, methodDeclarationScope);
    }
    /*
     * Print the method name
     */
    this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, true);

    formatMethodArguments(
      methodDeclaration,
      this.preferences.insert_space_before_opening_paren_in_method_declaration,
      this.preferences.insert_space_between_empty_parens_in_method_declaration,
      this.preferences.insert_space_before_closing_paren_in_method_declaration,
      this.preferences.insert_space_after_opening_paren_in_method_declaration,
      this.preferences.insert_space_before_comma_in_method_declaration_parameters,
      this.preferences.insert_space_after_comma_in_method_declaration_parameters,
      this.preferences.alignment_for_parameters_in_method_declaration);

    /*
     * Check for extra dimensions
     */
    int extraDimensions = getDimensions();
    if (extraDimensions != 0) {
       for (int i = 0; i < extraDimensions; i++) {
         this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET);
         this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET);
       }
    }
       
    formatThrowsClause(
      methodDeclaration,
      this.preferences.insert_space_before_comma_in_method_declaration_throws,
      this.preferences.insert_space_after_comma_in_method_declaration_throws,
      this.preferences.alignment_for_throws_clause_in_method_declaration);

    if (!methodDeclaration.isNative() && !methodDeclaration.isAbstract() && ((methodDeclaration.modifiers & ExtraCompilerModifiers.AccSemicolonBody) == 0)) {
      /*
       * Method body
       */
      String method_declaration_brace = this.preferences.brace_position_for_method_declaration;
            formatLeftCurlyBrace(line, method_declaration_brace);
      formatOpeningBrace(method_declaration_brace, this.preferences.insert_space_before_opening_brace_in_method_declaration);
      final int numberOfBlankLinesAtBeginningOfMethodBody = this.preferences.blank_lines_at_beginning_of_method_body;
      if (numberOfBlankLinesAtBeginningOfMethodBody > 0) {
        this.scribe.printEmptyLines(numberOfBlankLinesAtBeginningOfMethodBody);
      }
      final Statement[] statements = methodDeclaration.statements;
      if (statements != null) {
        this.scribe.printNewLine();
        if (this.preferences.indent_statements_compare_to_body) {
          this.scribe.indent();
        }
        formatStatements(methodDeclarationScope, statements, true);
        this.scribe.printComment();
        if (this.preferences.indent_statements_compare_to_body) {
          this.scribe.unIndent();
        }
      } else if (this.preferences.insert_new_line_in_empty_method_body) {
        this.scribe.printNewLine();
        if (this.preferences.indent_statements_compare_to_body) {
          this.scribe.indent();
        }
        this.scribe.printComment();
        if (this.preferences.indent_statements_compare_to_body) {
          this.scribe.unIndent();
        }
      }
      this.scribe.printNextToken(TerminalTokens.TokenNameRBRACE);
      this.scribe.printTrailingComment();
      if (method_declaration_brace.equals(DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED)) {
        this.scribe.unIndent();
      }
    } else {
      // no method body
      this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
      this.scribe.printTrailingComment();
    }
    return false;
  }
  public boolean visit(NormalAnnotation annotation, BlockScope scope) {
    this.scribe.printNextToken(TerminalTokens.TokenNameAT);
    if (this.preferences.insert_space_after_at_in_annotation) {
      this.scribe.space();
    }
    this.scribe.printQualifiedReference(annotation.sourceEnd);
    this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_annotation);
    if (this.preferences.insert_space_after_opening_paren_in_annotation) {
      this.scribe.space();
    }
    MemberValuePair[] memberValuePairs = annotation.memberValuePairs;
    if (memberValuePairs != null) {
      int length = memberValuePairs.length;
      for (int i = 0; i < length - 1; i++) {
        memberValuePairs[i].traverse(this, scope);
        this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_annotation);
        if (this.preferences.insert_space_after_comma_in_annotation) {
          this.scribe.space();
        }
      }
      memberValuePairs[length - 1].traverse(this, scope);
    }
    this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_annotation);
    return false;
  }
  /**
   * @see org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.aspectj.org.eclipse.jdt.internal.compiler.ast.NullLiteral, org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope)
   */
  public boolean visit(NullLiteral nullLiteral, BlockScope scope) {

    final int numberOfParens = (nullLiteral.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
    if (numberOfParens > 0) {
      manageOpeningParenthesizedExpression(nullLiteral, numberOfParens);
    }
    this.scribe.printNextToken(TerminalTokens.TokenNamenull);

    if (numberOfParens > 0) {
      manageClosingParenthesizedExpression(nullLiteral, numberOfParens);
    }
    return false;
  }


  /**
   * @see org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.aspectj.org.eclipse.jdt.internal.compiler.ast.OR_OR_Expression, org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope)
   */
  public boolean visit(OR_OR_Expression or_or_Expression, BlockScope scope) {
    return dumpBinaryExpression(or_or_Expression, TerminalTokens.TokenNameOR_OR, scope);
  }
  public boolean visit(
      ParameterizedQualifiedTypeReference parameterizedQualifiedTypeReference,
      BlockScope scope) {
    final int numberOfParens = (parameterizedQualifiedTypeReference.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
    if (numberOfParens > 0) {
      manageOpeningParenthesizedExpression(parameterizedQualifiedTypeReference, numberOfParens);
    }
    TypeReference[][] typeArguments = parameterizedQualifiedTypeReference.typeArguments;
    int length = typeArguments.length;
    for (int i = 0; i < length; i++) {
      this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier);
      TypeReference[] typeArgument = typeArguments[i];     
      if (typeArgument != null) {
        this.scribe.printNextToken(TerminalTokens.TokenNameLESS, this.preferences.insert_space_before_opening_angle_bracket_in_parameterized_type_reference);
        if (this.preferences.insert_space_after_opening_angle_bracket_in_parameterized_type_reference) {
          this.scribe.space();
        }
        int typeArgumentLength = typeArgument.length;
        for (int j = 0; j < typeArgumentLength - 1; j++) {
          typeArgument[j].traverse(this, scope);
          this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_parameterized_type_reference);
          if (this.preferences.insert_space_after_comma_in_parameterized_type_reference) {
            this.scribe.space();
          }     
        }
        typeArgument[typeArgumentLength - 1].traverse(this, scope);
        if (isClosingGenericToken()) {
          this.scribe.printNextToken(CLOSING_GENERICS_EXPECTEDTOKENS, this.preferences.insert_space_before_closing_angle_bracket_in_parameterized_type_reference);
        }
      }
      if (i < length - 1) {
        this.scribe.printNextToken(TerminalTokens.TokenNameDOT);
      }
    }
    int dimensions = getDimensions();
    if (dimensions != 0 && dimensions <= parameterizedQualifiedTypeReference.dimensions()) {
      if (this.preferences.insert_space_before_opening_bracket_in_array_type_reference) {
        this.scribe.space();
      }
      for (int i = 0; i < dimensions; i++) {
        this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET);
        if (this.preferences.insert_space_between_brackets_in_array_type_reference) {
          this.scribe.space();
        }
        this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET);
      }
    }   
    if (numberOfParens > 0) {
      manageClosingParenthesizedExpression(parameterizedQualifiedTypeReference, numberOfParens);
    }
    return false;
  }
  public boolean visit(
      ParameterizedQualifiedTypeReference parameterizedQualifiedTypeReference,
      ClassScope scope) {
    final int numberOfParens = (parameterizedQualifiedTypeReference.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
    if (numberOfParens > 0) {
      manageOpeningParenthesizedExpression(parameterizedQualifiedTypeReference, numberOfParens);
    }
    TypeReference[][] typeArguments = parameterizedQualifiedTypeReference.typeArguments;
    int length = typeArguments.length;
    for (int i = 0; i < length; i++) {
      this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier);
      TypeReference[] typeArgument = typeArguments[i];     
      if (typeArgument != null) {
        this.scribe.printNextToken(TerminalTokens.TokenNameLESS, this.preferences.insert_space_before_opening_angle_bracket_in_parameterized_type_reference);
        if (this.preferences.insert_space_after_opening_angle_bracket_in_parameterized_type_reference) {
          this.scribe.space();
        }
        int typeArgumentLength = typeArgument.length;
        for (int j = 0; j < typeArgumentLength - 1; j++) {
          typeArgument[j].traverse(this, scope);
          this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_parameterized_type_reference);
          if (this.preferences.insert_space_after_comma_in_parameterized_type_reference) {
            this.scribe.space();
          }     
        }
        typeArgument[typeArgumentLength - 1].traverse(this, scope);
        if (isClosingGenericToken()) {
          this.scribe.printNextToken(CLOSING_GENERICS_EXPECTEDTOKENS, this.preferences.insert_space_before_closing_angle_bracket_in_parameterized_type_reference);
        }
      }
      if (i < length - 1) {
        this.scribe.printNextToken(TerminalTokens.TokenNameDOT);
      }
    }
    int dimensions = getDimensions();
    if (dimensions != 0 && dimensions <= parameterizedQualifiedTypeReference.dimensions()) {
      if (this.preferences.insert_space_before_opening_bracket_in_array_type_reference) {
        this.scribe.space();
      }
      for (int i = 0; i < dimensions; i++) {
        this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET);
        if (this.preferences.insert_space_between_brackets_in_array_type_reference) {
          this.scribe.space();
        }
        this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET);
      }
    }   
    if (numberOfParens > 0) {
      manageClosingParenthesizedExpression(parameterizedQualifiedTypeReference, numberOfParens);
    }
    return false;
  }
  public boolean visit(
      ParameterizedSingleTypeReference parameterizedSingleTypeReference,
      BlockScope scope) {
    final int numberOfParens = (parameterizedSingleTypeReference.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
    if (numberOfParens > 0) {
      manageOpeningParenthesizedExpression(parameterizedSingleTypeReference, numberOfParens);
    }
    this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier);

    this.scribe.printNextToken(TerminalTokens.TokenNameLESS, this.preferences.insert_space_before_opening_angle_bracket_in_parameterized_type_reference);
    if (this.preferences.insert_space_after_opening_angle_bracket_in_parameterized_type_reference) {
      this.scribe.space();
    }
    TypeReference[] typeArguments = parameterizedSingleTypeReference.typeArguments;
    int typeArgumentsLength = typeArguments.length;
    for (int i = 0; i < typeArgumentsLength - 1; i++) {
      typeArguments[i].traverse(this, scope);
      this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_parameterized_type_reference);
      if (this.preferences.insert_space_after_comma_in_parameterized_type_reference) {
        this.scribe.space();
      }     
    }
    typeArguments[typeArgumentsLength - 1].traverse(this, scope);
    if (isClosingGenericToken()) {
      this.scribe.printNextToken(CLOSING_GENERICS_EXPECTEDTOKENS, this.preferences.insert_space_before_closing_angle_bracket_in_parameterized_type_reference);
    }
    int dimensions = getDimensions();
    if (dimensions != 0 && dimensions <= parameterizedSingleTypeReference.dimensions()) {
      if (this.preferences.insert_space_before_opening_bracket_in_array_type_reference) {
        this.scribe.space();
      }
      for (int i = 0; i < dimensions; i++) {
        this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET);
        if (this.preferences.insert_space_between_brackets_in_array_type_reference) {
          this.scribe.space();
        }
        this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET);
      }
    }   
    if (numberOfParens > 0) {
      manageClosingParenthesizedExpression(parameterizedSingleTypeReference, numberOfParens);
    }
    return false;
  }
  public boolean visit(
      ParameterizedSingleTypeReference parameterizedSingleTypeReference,
      ClassScope scope) {
    final int numberOfParens = (parameterizedSingleTypeReference.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
    if (numberOfParens > 0) {
      manageOpeningParenthesizedExpression(parameterizedSingleTypeReference, numberOfParens);
    }
    this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier);

    this.scribe.printNextToken(TerminalTokens.TokenNameLESS, this.preferences.insert_space_before_opening_angle_bracket_in_parameterized_type_reference);
    if (this.preferences.insert_space_after_opening_angle_bracket_in_parameterized_type_reference) {
      this.scribe.space();
    }
    TypeReference[] typeArguments = parameterizedSingleTypeReference.typeArguments;
    int typeArgumentsLength = typeArguments.length;
    for (int i = 0; i < typeArgumentsLength - 1; i++) {
      typeArguments[i].traverse(this, scope);
      this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_parameterized_type_reference);
      if (this.preferences.insert_space_after_comma_in_parameterized_type_reference) {
        this.scribe.space();
      }     
    }
    typeArguments[typeArgumentsLength - 1].traverse(this, scope);
    if (isClosingGenericToken()) {
      this.scribe.printNextToken(CLOSING_GENERICS_EXPECTEDTOKENS, this.preferences.insert_space_before_closing_angle_bracket_in_parameterized_type_reference);
    }
    int dimensions = getDimensions();
    if (dimensions != 0 && dimensions <= parameterizedSingleTypeReference.dimensions()) {
      if (this.preferences.insert_space_before_opening_bracket_in_array_type_reference) {
        this.scribe.space();
      }
      for (int i = 0; i < dimensions; i++) {
        this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET);
        if (this.preferences.insert_space_between_brackets_in_array_type_reference) {
          this.scribe.space();
        }
        this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET);
      }
    }   
    if (numberOfParens > 0) {
      manageClosingParenthesizedExpression(parameterizedSingleTypeReference, numberOfParens);
    }
    return false;
  }
 
  /**
   * @see org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.aspectj.org.eclipse.jdt.internal.compiler.ast.PostfixExpression, org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope)
   */
  public boolean visit(
    PostfixExpression postfixExpression,
    BlockScope scope) {

    final int numberOfParens = (postfixExpression.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
    if (numberOfParens > 0) {
      manageOpeningParenthesizedExpression(postfixExpression, numberOfParens);
    }
    postfixExpression.lhs.traverse(this, scope);
    int operator = postfixExpression.operator == OperatorIds.PLUS
      ? TerminalTokens.TokenNamePLUS_PLUS : TerminalTokens.TokenNameMINUS_MINUS;
    this.scribe.printNextToken(operator, this.preferences.insert_space_before_postfix_operator);
    if (this.preferences.insert_space_after_postfix_operator) {
      this.scribe.space();
    }
    if (numberOfParens > 0) {
      manageClosingParenthesizedExpression(postfixExpression, numberOfParens);
    }
    return false;
  }

  /**
   * @see org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.aspectj.org.eclipse.jdt.internal.compiler.ast.PrefixExpression, org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope)
   */
  public boolean visit(PrefixExpression prefixExpression, BlockScope scope) {

    final int numberOfParens = (prefixExpression.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
    if (numberOfParens > 0) {
      manageOpeningParenthesizedExpression(prefixExpression, numberOfParens);
    }
    int operator = prefixExpression.operator == OperatorIds.PLUS
      ? TerminalTokens.TokenNamePLUS_PLUS : TerminalTokens.TokenNameMINUS_MINUS;
    this.scribe.printNextToken(operator, this.preferences.insert_space_before_prefix_operator);
    if (this.preferences.insert_space_after_prefix_operator) {
      this.scribe.space();
    }
    prefixExpression.lhs.traverse(this, scope);
    if (numberOfParens > 0) {
      manageClosingParenthesizedExpression(prefixExpression, numberOfParens);
    }
    return false;
  }
 
  /**
   * @see org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.aspectj.org.eclipse.jdt.internal.compiler.ast.QualifiedAllocationExpression, org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope)
   */
  public boolean visit(
    QualifiedAllocationExpression qualifiedAllocationExpression,
    BlockScope scope) {
     
    final int numberOfParens = (qualifiedAllocationExpression.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
    if (numberOfParens > 0) {
      manageOpeningParenthesizedExpression(qualifiedAllocationExpression, numberOfParens);
    }
    final Expression enclosingInstance = qualifiedAllocationExpression.enclosingInstance;
    if (enclosingInstance != null) {
      enclosingInstance.traverse(this, scope);
      this.scribe.printNextToken(TerminalTokens.TokenNameDOT);
    }
   
    this.scribe.printNextToken(TerminalTokens.TokenNamenew);
    // used for the new line on wrap style of formatting
    TypeReference[] typeArguments = qualifiedAllocationExpression.typeArguments;
    if (typeArguments != null) {
        this.scribe.printNextToken(TerminalTokens.TokenNameLESS, this.preferences.insert_space_before_opening_angle_bracket_in_type_arguments);
        if (this.preferences.insert_space_after_opening_angle_bracket_in_type_arguments) {
          this.scribe.space();
        }
        int length = typeArguments.length;
        for (int i = 0; i < length - 1; i++) {
          typeArguments[i].traverse(this, scope);
          this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_type_arguments);
          if (this.preferences.insert_space_after_comma_in_type_arguments) {
            this.scribe.space();
          }       
        }
        typeArguments[length - 1].traverse(this, scope);
        if (isClosingGenericToken()) {
          this.scribe.printNextToken(CLOSING_GENERICS_EXPECTEDTOKENS, this.preferences.insert_space_before_closing_angle_bracket_in_type_arguments);
        }
        if (this.preferences.insert_space_after_closing_angle_bracket_in_type_arguments) {
          this.scribe.space();
        }
    } else {
      this.scribe.space();
    }

    final int line = this.scribe.line;
    qualifiedAllocationExpression.type.traverse(this, scope);
   
    this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_method_invocation);

    final Expression[] arguments = qualifiedAllocationExpression.arguments;
    if (arguments != null) {
      if (this.preferences.insert_space_after_opening_paren_in_method_invocation) {
        this.scribe.space();
      }
      int argumentLength = arguments.length;
      Alignment argumentsAlignment =this.scribe.createAlignment(
          "allocation",//$NON-NLS-1$
          this.preferences.alignment_for_arguments_in_qualified_allocation_expression,
          argumentLength,
          this.scribe.scanner.currentPosition);
      this.scribe.enterAlignment(argumentsAlignment);
      boolean ok = false;
      do {
        try {
          for (int i = 0; i < argumentLength; i++) {
            if (i > 0) {
              this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_allocation_expression);
              this.scribe.printTrailingComment();
            }
            this.scribe.alignFragment(argumentsAlignment, i);
            if (i > 0 && this.preferences.insert_space_after_comma_in_allocation_expression) {
              this.scribe.space();
            }
            arguments[i].traverse(this, scope);
          }
          ok = true;
        } catch (AlignmentException e) {
          this.scribe.redoAlignment(e);
        }
      } while (!ok);
      this.scribe.exitAlignment(argumentsAlignment, true);
      this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_method_invocation);
    } else {
      this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_between_empty_parens_in_method_invocation);
    }
    final TypeDeclaration anonymousType = qualifiedAllocationExpression.anonymousType;
    if (anonymousType != null) {
      formatLeftCurlyBrace(line, this.preferences.brace_position_for_anonymous_type_declaration);
      formatAnonymousTypeDeclaration(anonymousType);
    }
    if (numberOfParens > 0) {
      manageClosingParenthesizedExpression(qualifiedAllocationExpression, numberOfParens);
    }
    return false;
  }

  /**
   * @see org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.aspectj.org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference, org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope)
   */
  public boolean visit(
    QualifiedNameReference qualifiedNameReference,
    BlockScope scope) {

    final int numberOfParens = (qualifiedNameReference.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
    if (numberOfParens > 0) {
      manageOpeningParenthesizedExpression(qualifiedNameReference, numberOfParens);
    }
    this.scribe.printQualifiedReference(qualifiedNameReference.sourceEnd);

    if (numberOfParens > 0) {
      manageClosingParenthesizedExpression(qualifiedNameReference, numberOfParens);
    }
    return false;
  }

  /**
   * @see org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.aspectj.org.eclipse.jdt.internal.compiler.ast.QualifiedSuperReference, org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope)
   */
  public boolean visit(
    QualifiedSuperReference qualifiedSuperReference,
    BlockScope scope) {

    final int numberOfParens = (qualifiedSuperReference.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
    if (numberOfParens > 0) {
      manageOpeningParenthesizedExpression(qualifiedSuperReference, numberOfParens);
    }
    qualifiedSuperReference.qualification.traverse(this, scope);
    this.scribe.printNextToken(TerminalTokens.TokenNameDOT);
    this.scribe.printNextToken(TerminalTokens.TokenNamesuper);
   
    if (numberOfParens > 0) {
      manageClosingParenthesizedExpression(qualifiedSuperReference, numberOfParens);
    }
    return false;
  }

  /**
   * @see org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.aspectj.org.eclipse.jdt.internal.compiler.ast.QualifiedThisReference, org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope)
   */
  public boolean visit(
    QualifiedThisReference qualifiedThisReference,
    BlockScope scope) {

    final int numberOfParens = (qualifiedThisReference.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
    if (numberOfParens > 0) {
      manageOpeningParenthesizedExpression(qualifiedThisReference, numberOfParens);
    }
    qualifiedThisReference.qualification.traverse(this, scope);
    this.scribe.printNextToken(TerminalTokens.TokenNameDOT);
    this.scribe.printNextToken(TerminalTokens.TokenNamethis);
   
    if (numberOfParens > 0) {
      manageClosingParenthesizedExpression(qualifiedThisReference, numberOfParens);
    }
    return false;
  }

  /**
   * @see org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.aspectj.org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference, org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope)
   */
  public boolean visit(
    QualifiedTypeReference qualifiedTypeReference,
    BlockScope scope) {

    final int numberOfParens = (qualifiedTypeReference.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
    if (numberOfParens > 0) {
      manageOpeningParenthesizedExpression(qualifiedTypeReference, numberOfParens);
    }
    this.scribe.printQualifiedReference(qualifiedTypeReference.sourceEnd);
   
    if (numberOfParens > 0) {
      manageClosingParenthesizedExpression(qualifiedTypeReference, numberOfParens);
    }
    return false;
  }

  /**
   * @see org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.aspectj.org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference, org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ClassScope)
   */
  public boolean visit(
    QualifiedTypeReference qualifiedTypeReference,
    ClassScope scope) {

      final int numberOfParens = (qualifiedTypeReference.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
      if (numberOfParens > 0) {
        manageOpeningParenthesizedExpression(qualifiedTypeReference, numberOfParens);
      }
      this.scribe.printQualifiedReference(qualifiedTypeReference.sourceEnd);
     
      if (numberOfParens > 0) {
        manageClosingParenthesizedExpression(qualifiedTypeReference, numberOfParens);
      }
      return false;
  }

  /**
   * @see org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.aspectj.org.eclipse.jdt.internal.compiler.ast.ReturnStatement, org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope)
   */
  public boolean visit(ReturnStatement returnStatement, BlockScope scope) {
   
    this.scribe.printNextToken(TerminalTokens.TokenNamereturn);
    final Expression expression = returnStatement.expression;
    if (expression != null) {
      final int numberOfParens = (expression.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
      if ((numberOfParens != 0 && this.preferences.insert_space_before_parenthesized_expression_in_return)
          || numberOfParens == 0) {
        this.scribe.space();
      }
      expression.traverse(this, scope);
    }
    /*
     * Print the semi-colon
     */ 
    this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
    this.scribe.printTrailingComment();
    return false;
  }
  public boolean visit(SingleMemberAnnotation annotation, BlockScope scope) {
    this.scribe.printNextToken(TerminalTokens.TokenNameAT);
    if (this.preferences.insert_space_after_at_in_annotation) {
      this.scribe.space();
    }
    this.scribe.printQualifiedReference(annotation.sourceEnd);
    this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_annotation);
    if (this.preferences.insert_space_after_opening_paren_in_annotation) {
      this.scribe.space();
    }
    annotation.memberValue.traverse(this, scope);
    this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_annotation);
    return false;
  }
  /**
   * @see org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.aspectj.org.eclipse.jdt.internal.compiler.ast.SingleNameReference, org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope)
   */
  public boolean visit(SingleNameReference singleNameReference, BlockScope scope) {

    final int numberOfParens = (singleNameReference.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
    if (numberOfParens > 0) {
      manageOpeningParenthesizedExpression(singleNameReference, numberOfParens);
    }
    this.scribe.printNextToken(SINGLETYPEREFERENCE_EXPECTEDTOKENS);
   
    if (numberOfParens > 0) {
      manageClosingParenthesizedExpression(singleNameReference, numberOfParens);
    }
    return false;
  }

  /**
   * @see org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.aspectj.org.eclipse.jdt.internal.compiler.ast.SingleTypeReference, org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope)
   */
  public boolean visit(
    SingleTypeReference singleTypeReference,
    BlockScope scope) {

    final int numberOfParens = (singleTypeReference.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
    if (numberOfParens > 0) {
      manageOpeningParenthesizedExpression(singleTypeReference, numberOfParens);
    }
    this.scribe.printNextToken(SINGLETYPEREFERENCE_EXPECTEDTOKENS);

    if (numberOfParens > 0) {
      manageClosingParenthesizedExpression(singleTypeReference, numberOfParens);
    }
    return false;
  }

  /**
   * @see org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.aspectj.org.eclipse.jdt.internal.compiler.ast.SingleTypeReference, org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ClassScope)
   */
  public boolean visit(
    SingleTypeReference singleTypeReference,
    ClassScope scope) {

    final int numberOfParens = (singleTypeReference.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
    if (numberOfParens > 0) {
      manageOpeningParenthesizedExpression(singleTypeReference, numberOfParens);
    }
    this.scribe.printNextToken(SINGLETYPEREFERENCE_EXPECTEDTOKENS);

    if (numberOfParens > 0) {
      manageClosingParenthesizedExpression(singleTypeReference, numberOfParens);
    }
    return false;
  }

  /**
   * @see org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.aspectj.org.eclipse.jdt.internal.compiler.ast.StringLiteral, org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope)
   */
  public boolean visit(StringLiteral stringLiteral, BlockScope scope) {
    final int numberOfParens = (stringLiteral.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
    if (numberOfParens > 0) {
      manageOpeningParenthesizedExpression(stringLiteral, numberOfParens);
    }
    this.scribe.checkNLSTag(stringLiteral.sourceStart);
    this.scribe.printNextToken(TerminalTokens.TokenNameStringLiteral);
    this.scribe.printTrailingComment();
    if (numberOfParens > 0) {
      manageClosingParenthesizedExpression(stringLiteral, numberOfParens);
    }
    return false;
  }

  /**
   * @see org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.aspectj.org.eclipse.jdt.internal.compiler.ast.NullLiteral, org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope)
   */
  public boolean visit(StringLiteralConcatenation stringLiteral, BlockScope scope) {
    final int numberOfParens = (stringLiteral.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
    if (numberOfParens > 0) {
      manageOpeningParenthesizedExpression(stringLiteral, numberOfParens);
    }

    this.scribe.printComment();
    ASTNode[] fragments = stringLiteral.literals;
    int fragmentsSize = stringLiteral.counter;
    Alignment binaryExpressionAlignment = this.scribe.createAlignment("binaryExpressionAlignment", this.preferences.alignment_for_binary_expression, Alignment.R_OUTERMOST, fragmentsSize, this.scribe.scanner.currentPosition); //$NON-NLS-1$
    this.scribe.enterAlignment(binaryExpressionAlignment);
    boolean ok = false;
    do {
      try {
        for (int i = 0; i < fragmentsSize - 1; i++) {
          ASTNode fragment = fragments[i];
          fragment.traverse(this, scope);
          this.scribe.printTrailingComment();
          if (this.scribe.lastNumberOfNewLines == 1) {
            // a new line has been inserted by printTrailingComment()
            this.scribe.indentationLevel = binaryExpressionAlignment.breakIndentationLevel;
          }
          this.scribe.alignFragment(binaryExpressionAlignment, i);
          this.scribe.printNextToken(TerminalTokens.TokenNamePLUS, this.preferences.insert_space_before_binary_operator);
          if (this.preferences.insert_space_after_binary_operator) {
            this.scribe.space();
          }
        }
        fragments[fragmentsSize - 1].traverse(this, scope);
        this.scribe.printTrailingComment();
        ok = true;
      } catch(AlignmentException e){
        this.scribe.redoAlignment(e);
      }
    } while (!ok);   
    this.scribe.exitAlignment(binaryExpressionAlignment, true);
 
    if (numberOfParens > 0) {
      manageClosingParenthesizedExpression(stringLiteral, numberOfParens);
    }
    return false;
  }

  /**
   * @see org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.aspectj.org.eclipse.jdt.internal.compiler.ast.SuperReference, org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope)
   */
  public boolean visit(SuperReference superReference, BlockScope scope) {

    final int numberOfParens = (superReference.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
    if (numberOfParens > 0) {
      manageOpeningParenthesizedExpression(superReference, numberOfParens);
    }
    this.scribe.printNextToken(TerminalTokens.TokenNamesuper);

    if (numberOfParens > 0) {
      manageClosingParenthesizedExpression(superReference, numberOfParens);
    }
    return false;
  }

  /**
   * @see org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.aspectj.org.eclipse.jdt.internal.compiler.ast.SwitchStatement, org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope)
   */
  public boolean visit(SwitchStatement switchStatement, BlockScope scope) {
    this.scribe.printNextToken(TerminalTokens.TokenNameswitch);
    this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_switch);
   
    if (this.preferences.insert_space_after_opening_paren_in_switch) {
      this.scribe.space();
    }
   
    switchStatement.expression.traverse(this, scope);
    this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_switch);
    /*
     * Type body
     */
    String switch_brace = this.preferences.brace_position_for_switch;
    formatOpeningBrace(switch_brace, this.preferences.insert_space_before_opening_brace_in_switch);
    this.scribe.printNewLine();

    if (this.preferences.indent_switchstatements_compare_to_switch) {
      this.scribe.indent();
    }
    final Statement[] statements = switchStatement.statements;
    boolean wasACase = false;
    boolean wasAStatement = false;
    if (statements != null) {
      int statementsLength = statements.length;
      for (int i = 0; i < statementsLength; i++) {
        final Statement statement = statements[i];
        if (statement instanceof CaseStatement) {
          if (wasACase) {
            this.scribe.printNewLine();
          }
          if ((wasACase && this.preferences.indent_switchstatements_compare_to_cases)
            || (wasAStatement && this.preferences.indent_switchstatements_compare_to_cases)) {
            this.scribe.unIndent();
          }
          statement.traverse(this, scope);
          this.scribe.printTrailingComment();
          wasACase = true;
          wasAStatement = false;
          if (this.preferences.indent_switchstatements_compare_to_cases) {
            this.scribe.indent();
          }
        } else if (statement instanceof BreakStatement) {
          if (this.preferences.indent_breaks_compare_to_cases) {
            if (wasAStatement && !this.preferences.indent_switchstatements_compare_to_cases) {
              this.scribe.indent();
            }
          } else {
            if (wasAStatement) {
              if (this.preferences.indent_switchstatements_compare_to_cases) {
                this.scribe.unIndent();
              }
            }
            if (wasACase && this.preferences.indent_switchstatements_compare_to_cases) {
              this.scribe.unIndent();
            }
          }
          if (wasACase) {
            this.scribe.printNewLine();
          }
          statement.traverse(this, scope);
          if (this.preferences.indent_breaks_compare_to_cases) {
            this.scribe.unIndent();
          }
          wasACase = false;
          wasAStatement = false;
        } else if (statement instanceof Block) {
          String bracePosition;
          if (wasACase) {
            if (this.preferences.indent_switchstatements_compare_to_cases) {
              this.scribe.unIndent();
            }
            bracePosition =  this.preferences.brace_position_for_block_in_case;
            formatBlock((Block) statement, scope, bracePosition, this.preferences.insert_space_after_colon_in_case);
            if (this.preferences.indent_switchstatements_compare_to_cases) {
              this.scribe.indent();
            }
          } else {
            bracePosition =  this.preferences.brace_position_for_block;
            formatBlock((Block) statement, scope, bracePosition, this.preferences.insert_space_before_opening_brace_in_block);
          }
          wasAStatement = true;
          wasACase = false;
        } else {
          this.scribe.printNewLine();
          statement.traverse(this, scope);
          wasAStatement = true;
          wasACase = false;
        }
        if (statement instanceof Expression) {
          /*
           * Print the semi-colon
           */ 
          this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
          this.scribe.printTrailingComment();
          this.scribe.printNewLine();
        } else if (statement instanceof LocalDeclaration) {
          LocalDeclaration currentLocal = (LocalDeclaration) statement;
          if (i < (statementsLength - 1)) {
            /*
             * We need to check that the next statement is a local declaration
             */
            if (statements[i + 1] instanceof LocalDeclaration) {
              LocalDeclaration nextLocal = (LocalDeclaration) statements[i + 1];
              if (currentLocal.declarationSourceStart != nextLocal.declarationSourceStart) {
                /*
                 * Print the semi-colon
                 */ 
                this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
                this.scribe.printTrailingComment();
                this.scribe.printNewLine();
              }
            } else {
              /*
               * Print the semi-colon
               */ 
              this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
              this.scribe.printTrailingComment();
              this.scribe.printNewLine();
            }
          } else {
            /*
             * Print the semi-colon
             */ 
            this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
            this.scribe.printTrailingComment();
            this.scribe.printNewLine();
          }
        } else if (!wasACase) {
          this.scribe.printNewLine();
        }
        this.scribe.printComment();
      }
    }
   
    if ((wasACase || wasAStatement) && this.preferences.indent_switchstatements_compare_to_cases) {
      this.scribe.unIndent();
    }
    if (this.preferences.indent_switchstatements_compare_to_switch) {
      this.scribe.unIndent();
    }
    this.scribe.printNewLine();
    this.scribe.printNextToken(TerminalTokens.TokenNameRBRACE);
    this.scribe.printTrailingComment();
    if (switch_brace.equals(DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED)) {
      this.scribe.unIndent();
    }   
    return false;
  }

  /**
   * @see org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.aspectj.org.eclipse.jdt.internal.compiler.ast.SynchronizedStatement, org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope)
   */
  public boolean visit(
    SynchronizedStatement synchronizedStatement,
    BlockScope scope) {
   
    this.scribe.printNextToken(TerminalTokens.TokenNamesynchronized);

    final int line = this.scribe.line;

    this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_synchronized);
   
    if (this.preferences.insert_space_after_opening_paren_in_synchronized) {
      this.scribe.space();
    }
    synchronizedStatement.expression.traverse(this, scope);
 
    this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_synchronized);
   
    formatLeftCurlyBrace(line, this.preferences.brace_position_for_block);
    synchronizedStatement.block.traverse(this, scope);
    return false;
  }
  /**
   * @see org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.aspectj.org.eclipse.jdt.internal.compiler.ast.ThisReference, org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope)
   */
  public boolean visit(ThisReference thisReference, BlockScope scope) {
   
    if (!thisReference.isImplicitThis()) {
      final int numberOfParens = (thisReference.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
      if (numberOfParens > 0) {
        manageOpeningParenthesizedExpression(thisReference, numberOfParens);
      }
      this.scribe.printNextToken(TerminalTokens.TokenNamethis);
     
      if (numberOfParens > 0) {
        manageClosingParenthesizedExpression(thisReference, numberOfParens);
      }
    }
    return false;
  }

  /**
   * @see org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.aspectj.org.eclipse.jdt.internal.compiler.ast.ThrowStatement, org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope)
   */
  public boolean visit(ThrowStatement throwStatement, BlockScope scope) {

    this.scribe.printNextToken(TerminalTokens.TokenNamethrow);
    Expression expression = throwStatement.exception;
    final int numberOfParens = (expression.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
    if ((numberOfParens > 0 && this.preferences.insert_space_before_parenthesized_expression_in_throw)
        || numberOfParens == 0) {
      this.scribe.space();
    }
    expression.traverse(this, scope);
    /*
     * Print the semi-colon
     */ 
    this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
    this.scribe.printTrailingComment();
    return false;
  }

  /**
   * @see org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.aspectj.org.eclipse.jdt.internal.compiler.ast.TrueLiteral, org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope)
   */
  public boolean visit(TrueLiteral trueLiteral, BlockScope scope) {

    final int numberOfParens = (trueLiteral.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
    if (numberOfParens > 0) {
      manageOpeningParenthesizedExpression(trueLiteral, numberOfParens);
    }
    this.scribe.printNextToken(TerminalTokens.TokenNametrue);

    if (numberOfParens > 0) {
      manageClosingParenthesizedExpression(trueLiteral, numberOfParens);
    }
    return false;
  }

  /**
   * @see org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.aspectj.org.eclipse.jdt.internal.compiler.ast.TryStatement, org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope)
   */
  public boolean visit(TryStatement tryStatement, BlockScope scope) {

    this.scribe.printNextToken(TerminalTokens.TokenNametry);
    tryStatement.tryBlock.traverse(this, scope);
    if (tryStatement.catchArguments != null) {
      for (int i = 0, max = tryStatement.catchBlocks.length; i < max; i++) {
        if (this.preferences.insert_new_line_before_catch_in_try_statement) {
          this.scribe.printNewLine();
       
        this.scribe.printNextToken(TerminalTokens.TokenNamecatch, this.preferences.insert_space_after_closing_brace_in_block);
        final int line = this.scribe.line;
        this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_catch);
       
        if (this.preferences.insert_space_after_opening_paren_in_catch) {
          this.scribe.space();
        }
       
        tryStatement.catchArguments[i].traverse(this, scope);
     
        this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_catch);
       
        formatLeftCurlyBrace(line, this.preferences.brace_position_for_block);
        tryStatement.catchBlocks[i].traverse(this, scope);
      }
    }
    if (tryStatement.finallyBlock != null) {
      if (this.preferences.insert_new_line_before_finally_in_try_statement) {
        this.scribe.printNewLine();
     
      this.scribe.printNextToken(TerminalTokens.TokenNamefinally, this.preferences.insert_space_after_closing_brace_in_block);
      tryStatement.finallyBlock.traverse(this, scope);
    }
    return false;
  }

  /**
   * @see org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeDeclaration, org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope)
   */
  public boolean visit(
    TypeDeclaration localTypeDeclaration,
    BlockScope scope) {

      format(localTypeDeclaration);
      return false;
  }

  /**
   * @see org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeDeclaration, org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ClassScope)
   */
  public boolean visit(TypeDeclaration memberTypeDeclaration, ClassScope scope) {
    format(memberTypeDeclaration)
    return false;
  }
 
  /**
   * @see org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeDeclaration, org.aspectj.org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope)
   */
  public boolean visit(
    TypeDeclaration typeDeclaration,
    CompilationUnitScope scope) {

    format(typeDeclaration);
    return false;
  }
  public boolean visit(TypeParameter typeParameter, BlockScope scope) {
    this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier);
    if (typeParameter.type != null) {
      this.scribe.space();
      this.scribe.printNextToken(TerminalTokens.TokenNameextends, true);
      this.scribe.space();
      typeParameter.type.traverse(this, scope);
    }
    final TypeReference[] bounds = typeParameter.bounds;
    if (bounds != null) {
      this.scribe.printNextToken(TerminalTokens.TokenNameAND, this.preferences.insert_space_before_and_in_type_parameter);
      if (this.preferences.insert_space_after_and_in_type_parameter) {
        this.scribe.space();
      }
      int boundsLength = bounds.length;
      for (int i = 0; i < boundsLength - 1; i++) {
        bounds[i].traverse(this, scope);
        this.scribe.printNextToken(TerminalTokens.TokenNameAND, this.preferences.insert_space_before_and_in_type_parameter);
        if (this.preferences.insert_space_after_and_in_type_parameter) {
          this.scribe.space();
        }
      }
      bounds[boundsLength - 1].traverse(this, scope);
    }
    return false;
  }
  public boolean visit(TypeParameter typeParameter, ClassScope scope) {
    this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier);
    if (typeParameter.type != null) {
      this.scribe.space();
      this.scribe.printNextToken(TerminalTokens.TokenNameextends, true);
      this.scribe.space();
      typeParameter.type.traverse(this, scope);
    }
    final TypeReference[] bounds = typeParameter.bounds;
    if (bounds != null) {
      this.scribe.printNextToken(TerminalTokens.TokenNameAND, this.preferences.insert_space_before_and_in_type_parameter);
      if (this.preferences.insert_space_after_and_in_type_parameter) {
        this.scribe.space();
      }
      int boundsLength = bounds.length;
      for (int i = 0; i < boundsLength - 1; i++) {
        bounds[i].traverse(this, scope);
        this.scribe.printNextToken(TerminalTokens.TokenNameAND, this.preferences.insert_space_before_and_in_type_parameter);
        if (this.preferences.insert_space_after_and_in_type_parameter) {
          this.scribe.space();
        }
      }
      bounds[boundsLength - 1].traverse(this, scope);
    }
    return false;
  }

  /**
   * @see org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.aspectj.org.eclipse.jdt.internal.compiler.ast.UnaryExpression, org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope)
   */
  public boolean visit(UnaryExpression unaryExpression, BlockScope scope) {

    final int numberOfParens = (unaryExpression.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
    if (numberOfParens > 0) {
      manageOpeningParenthesizedExpression(unaryExpression, numberOfParens);
    }

    /*
     * Print the operator
     */
    int operator;
    int operatorValue = (unaryExpression.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT;
    switch(operatorValue) {
      case OperatorIds.PLUS:
        operator = TerminalTokens.TokenNamePLUS;
        break;
      case OperatorIds.MINUS:
        operator = TerminalTokens.TokenNameMINUS;
        break;
      case OperatorIds.TWIDDLE:
        operator = TerminalTokens.TokenNameTWIDDLE;
        break;
      default:
        operator = TerminalTokens.TokenNameNOT;
    }

    this.scribe.printNextToken(operator, this.preferences.insert_space_before_unary_operator);
    if (this.preferences.insert_space_after_unary_operator) {
      this.scribe.space();
    }
    Expression expression = unaryExpression.expression;

    if (expression instanceof PrefixExpression) {
      PrefixExpression prefixExpression = (PrefixExpression) expression;
      final int numberOfParensForExpression = (prefixExpression.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
      if (numberOfParensForExpression == 0) {
        switch(operatorValue) {
          case OperatorIds.PLUS:
            if (prefixExpression.operator == OperatorIds.PLUS) {
              this.scribe.space();
            }           
            break;
          case OperatorIds.MINUS:
            if (prefixExpression.operator == OperatorIds.MINUS) {
              this.scribe.space();
            }           
            break;
        }
      }
      expression.traverse(this, scope);
    } else {
      expression.traverse(this, scope);
    }

    if (numberOfParens > 0) {
      manageClosingParenthesizedExpression(unaryExpression, numberOfParens);
    }
    return false;
  }

  /**
   * @see org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.aspectj.org.eclipse.jdt.internal.compiler.ast.WhileStatement, org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope)
   */
  public boolean visit(WhileStatement whileStatement, BlockScope scope) {

    this.scribe.printNextToken(TerminalTokens.TokenNamewhile);
    final int line = this.scribe.line;
    this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_opening_paren_in_while);
   
    if (this.preferences.insert_space_after_opening_paren_in_while) {
      this.scribe.space();
    }
    whileStatement.condition.traverse(this, scope);
   
    this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_while);
   
    final Statement action = whileStatement.action;
    if (action != null) {
      if (action instanceof Block) {
                formatLeftCurlyBrace(line, this.preferences.brace_position_for_block);
        action.traverse(this, scope);
      } else if (action instanceof EmptyStatement) {
        /*
         * This is an empty statement
         */
        formatNecessaryEmptyStatement();
      } else {
        this.scribe.printNewLine();
        this.scribe.indent();
        action.traverse(this, scope);
        if (action instanceof Expression) {
          this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
          this.scribe.printTrailingComment();
        }
        this.scribe.unIndent();
      }
    } else {
      /*
       * This is an empty statement
       */
      formatNecessaryEmptyStatement();
    }
    return false;
  }
  public boolean visit(Wildcard wildcard, BlockScope scope) {
    this.scribe.printNextToken(TerminalTokens.TokenNameQUESTION, this.preferences.insert_space_before_question_in_wilcard);
    switch(wildcard.kind) {
      case Wildcard.SUPER :
        this.scribe.printNextToken(TerminalTokens.TokenNamesuper, true);       
        this.scribe.space();
        wildcard.bound.traverse(this, scope);
        break;
      case Wildcard.EXTENDS :
        this.scribe.printNextToken(TerminalTokens.TokenNameextends, true);       
        this.scribe.space();
        wildcard.bound.traverse(this, scope);
        break;
      case Wildcard.UNBOUND :
        if (this.preferences.insert_space_after_question_in_wilcard) {
          this.scribe.space();
        }
    }
    return false;
  }
  public boolean visit(Wildcard wildcard, ClassScope scope) {
    this.scribe.printNextToken(TerminalTokens.TokenNameQUESTION, this.preferences.insert_space_before_question_in_wilcard);
    switch(wildcard.kind) {
      case Wildcard.SUPER :
        this.scribe.printNextToken(TerminalTokens.TokenNamesuper, true);       
        this.scribe.space();
        wildcard.bound.traverse(this, scope);
        break;
      case Wildcard.EXTENDS :
        this.scribe.printNextToken(TerminalTokens.TokenNameextends, true);       
        this.scribe.space();
        wildcard.bound.traverse(this, scope);
        break;
      case Wildcard.UNBOUND :
        if (this.preferences.insert_space_after_question_in_wilcard) {
          this.scribe.space();
        }
    }
    return false;
  }
}
TOP

Related Classes of org.aspectj.org.eclipse.jdt.internal.formatter.CodeFormatterVisitor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.