/*******************************************************************************
 * Copyright (c) 2014, 2019 Mateusz Matela and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     Mateusz Matela <mateusz.matela@gmail.com> - [formatter] Formatter does not format Java code correctly, especially when max line width is set - https://bugs.eclipse.org/303519
 *     Mateusz Matela <mateusz.matela@gmail.com> - [formatter] IndexOutOfBoundsException in TokenManager - https://bugs.eclipse.org/462945
 *     Mateusz Matela <mateusz.matela@gmail.com> - [formatter] follow up bug for comments - https://bugs.eclipse.org/458208
 *     IBM Corporation - DOM AST changes for JEP 354
 *******************************************************************************/
package org.eclipse.jdt.internal.formatter;

import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameAT;
import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameCOLON;
import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameCOMMA;
import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameCOMMENT_JAVADOC;
import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameLBRACE;
import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameRBRACE;
import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameSEMICOLON;
import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNamebase;
import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameelse;
import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNamefinally;
import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNamewhen;
import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNamewhile;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ASTVisitor;
import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
import org.eclipse.jdt.core.dom.Annotation;
import org.eclipse.jdt.core.dom.AnnotationTypeDeclaration;
import org.eclipse.jdt.core.dom.AnnotationTypeMemberDeclaration;
import org.eclipse.jdt.core.dom.AnonymousClassDeclaration;
import org.eclipse.jdt.core.dom.ArrayInitializer;
import org.eclipse.jdt.core.dom.Block;
import org.eclipse.jdt.core.dom.BodyDeclaration;
import org.eclipse.jdt.core.dom.BreakStatement;
import org.eclipse.jdt.core.dom.CallinMappingDeclaration;
import org.eclipse.jdt.core.dom.CalloutMappingDeclaration;
import org.eclipse.jdt.core.dom.CatchClause;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.ContinueStatement;
import org.eclipse.jdt.core.dom.DoStatement;
import org.eclipse.jdt.core.dom.EmptyStatement;
import org.eclipse.jdt.core.dom.EnhancedForStatement;
import org.eclipse.jdt.core.dom.EnumConstantDeclaration;
import org.eclipse.jdt.core.dom.EnumDeclaration;
import org.eclipse.jdt.core.dom.FieldDeclaration;
import org.eclipse.jdt.core.dom.ForStatement;
import org.eclipse.jdt.core.dom.GuardPredicateDeclaration;
import org.eclipse.jdt.core.dom.IfStatement;
import org.eclipse.jdt.core.dom.ImportDeclaration;
import org.eclipse.jdt.core.dom.Initializer;
import org.eclipse.jdt.core.dom.LabeledStatement;
import org.eclipse.jdt.core.dom.LambdaExpression;
import org.eclipse.jdt.core.dom.MarkerAnnotation;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.Modifier;
import org.eclipse.jdt.core.dom.ModuleDeclaration;
import org.eclipse.jdt.core.dom.ModuleDirective;
import org.eclipse.jdt.core.dom.NormalAnnotation;
import org.eclipse.jdt.core.dom.PackageDeclaration;
import org.eclipse.jdt.core.dom.ReturnStatement;
import org.eclipse.jdt.core.dom.RoleTypeDeclaration;
import org.eclipse.jdt.core.dom.SingleMemberAnnotation;
import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
import org.eclipse.jdt.core.dom.Statement;
import org.eclipse.jdt.core.dom.SwitchCase;
import org.eclipse.jdt.core.dom.SwitchExpression;
import org.eclipse.jdt.core.dom.SwitchStatement;
import org.eclipse.jdt.core.dom.ThrowStatement;
import org.eclipse.jdt.core.dom.TryStatement;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.jdt.core.dom.VariableDeclarationExpression;
import org.eclipse.jdt.core.dom.VariableDeclarationStatement;
import org.eclipse.jdt.core.dom.WhileStatement;
import org.eclipse.jdt.core.dom.WithinStatement;
import org.eclipse.jdt.core.dom.YieldStatement;
import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants;
import org.eclipse.jdt.core.dom.AbstractMethodMappingDeclaration;

public class LineBreaksPreparator extends ASTVisitor {
	final private TokenManager tm;
	final private DefaultCodeFormatterOptions options;

	private boolean declarationModifierVisited;

	public LineBreaksPreparator(TokenManager tokenManager, DefaultCodeFormatterOptions options) {
		this.tm = tokenManager;
		this.options = options;
	}

	@Override
	public boolean preVisit2(ASTNode node) {
		boolean isMalformed = (node.getFlags() & ASTNode.MALFORMED) != 0;
		return !isMalformed;
	}

	@Override
	public boolean visit(CompilationUnit node) {
		List<ImportDeclaration> imports = node.imports();
		if (!imports.isEmpty() && this.tm.firstIndexIn(imports.get(0), -1) > 0)
			putBlankLinesBefore(imports.get(0), this.options.blank_lines_before_imports);

		for (int i = 1; i < imports.size(); i++) {
			int from = this.tm.lastIndexIn(imports.get(i - 1), -1);
			int to = this.tm.firstIndexIn(imports.get(i), -1);
			for (int j = from; j < to; j++) {
				Token token1 = this.tm.get(j);
				Token token2 = this.tm.get(j + 1);
				if (this.tm.countLineBreaksBetween(token1, token2) > 1)
					putBlankLinesAfter(token1, this.options.blank_lines_between_import_groups);
			}
		}

		List<AnnotationTypeDeclaration> types = node.types();
		if (!types.isEmpty()) {
			if (!imports.isEmpty())
				putBlankLinesBefore(types.get(0), this.options.blank_lines_after_imports);
			for (int i = 1; i < types.size(); i++)
				putBlankLinesBefore(types.get(i), this.options.blank_lines_between_type_declarations);
		}
		return true;
	}

	@Override
	public boolean visit(PackageDeclaration node) {
		if (node.getJavadoc() == null) {
			putBlankLinesBefore(node, this.options.blank_lines_before_package);
		} else {
			putBlankLinesAfter(this.tm.lastTokenIn(node.getJavadoc(), -1), this.options.blank_lines_before_package);
		}

		putBlankLinesAfter(this.tm.lastTokenIn(node, -1), this.options.blank_lines_after_package);
		this.declarationModifierVisited = false;
		return true;
	}

	@Override
	public boolean visit(ImportDeclaration node) {
		breakLineBefore(node);
		return true;
	}

	@Override
	public boolean visit(TypeDeclaration node) {
//{ObjectTeams:
		GuardPredicateDeclaration predicate = node.getGuardPredicate();
		if (predicate != null) {
			this.tm.firstTokenIn(node.getGuardPredicate(), predicate.isBase() ? TokenNamebase : TokenNamewhen).breakBefore();
			indent(node.getGuardPredicate());
			indent(node.getGuardPredicate());
			this.tm.firstTokenAfter(node.getGuardPredicate(), TokenNameLBRACE).breakBefore();
		}			
// SH}
		handleBodyDeclarations(node.bodyDeclarations());

		if (node.getName().getStartPosition() == -1)
			return true; // this is a fake type created by parsing in class body mode

		breakLineBefore(node);

		handleBracedCode(node, node.getName(), this.options.brace_position_for_type_declaration,
				this.options.indent_body_declarations_compare_to_type_header);

		this.declarationModifierVisited = false;
		return true;
	}

	private void handleBodyDeclarations(List<BodyDeclaration> bodyDeclarations) {
		BodyDeclaration previous = null;
		for (BodyDeclaration bodyDeclaration : bodyDeclarations) {
			int blankLines = 0;
			if (previous == null) {
				blankLines = this.options.blank_lines_before_first_class_body_declaration;
			} else if (!sameChunk(previous, bodyDeclaration)) {
				blankLines = this.options.blank_lines_before_new_chunk;
			} else if (bodyDeclaration instanceof FieldDeclaration) {
				blankLines = this.options.blank_lines_before_field;
			} else if (bodyDeclaration instanceof AbstractTypeDeclaration) {
				blankLines = this.options.blank_lines_before_member_type;
			} else if (bodyDeclaration instanceof MethodDeclaration) {
				blankLines = ((MethodDeclaration) bodyDeclaration).getBody() == null
						&& ((MethodDeclaration) previous).getBody() == null
								? this.options.blank_lines_before_abstract_method
								: this.options.blank_lines_before_method;
			} else if (bodyDeclaration instanceof AnnotationTypeMemberDeclaration) {
				blankLines = this.options.blank_lines_before_method;
//{ObjectTeams: method mappings like methods:
			} else if (bodyDeclaration instanceof AbstractMethodMappingDeclaration) {
				blankLines = this.options.blank_lines_before_method;
// SH}
			}
			putBlankLinesBefore(bodyDeclaration, blankLines);
			previous = bodyDeclaration;
		}
		if (previous != null) {
			Token lastToken = this.tm.lastTokenIn(previous.getParent(), -1);
			if (lastToken.tokenType == TokenNameRBRACE) // otherwise it's a fake type
				putBlankLinesBefore(lastToken, this.options.blank_lines_after_last_class_body_declaration);
		}
	}

	private boolean sameChunk(BodyDeclaration bd1, BodyDeclaration bd2) {
		if (bd1.getClass().equals(bd2.getClass()))
			return true;
		if (bd1 instanceof AbstractTypeDeclaration && bd2 instanceof AbstractTypeDeclaration)
			return true;
		if ((bd1 instanceof FieldDeclaration || bd1 instanceof Initializer)
				&& (bd2 instanceof FieldDeclaration || bd2 instanceof Initializer))
			return true; // special case: initializers are often related to fields, don't separate
		return false;
	}

	@Override
	public boolean visit(EnumDeclaration node) {
		handleBracedCode(node, node.getName(), this.options.brace_position_for_enum_declaration,
				this.options.indent_body_declarations_compare_to_enum_declaration_header);

		List<BodyDeclaration> declarations = node.bodyDeclarations();
		List<EnumConstantDeclaration> enumConstants = node.enumConstants();
		if (!declarations.isEmpty()) {
			if (!enumConstants.isEmpty()) {
				declarations = new ArrayList<>(declarations);
				declarations.add(0, enumConstants.get(0));
			}
			handleBodyDeclarations(declarations);
		}

		for (int i = 0; i < enumConstants.size(); i++) {
			EnumConstantDeclaration declaration = enumConstants.get(i);
			if (declaration.getJavadoc() != null)
				this.tm.firstTokenIn(declaration, TokenNameCOMMENT_JAVADOC).breakBefore();
			if (declaration.getAnonymousClassDeclaration() != null && i < enumConstants.size() - 1)
				this.tm.firstTokenAfter(declaration, TokenNameCOMMA).breakAfter();
		}

		// put breaks after semicolons
		int index = enumConstants.isEmpty() ? this.tm.firstIndexAfter(node.getName(), TokenNameLBRACE) + 1
				: this.tm.firstIndexAfter(enumConstants.get(enumConstants.size() - 1), -1);
		for (;; index++) {
			Token token = this.tm.get(index);
			if (token.isComment())
				continue;
			if (token.tokenType == TokenNameSEMICOLON)
				token.breakAfter();
			else
				break;
		}

		this.declarationModifierVisited = false;
		return true;
	}

	@Override
	public boolean visit(AnnotationTypeDeclaration node) {
		handleBracedCode(node, node.getName(), this.options.brace_position_for_annotation_type_declaration,
				this.options.indent_body_declarations_compare_to_annotation_declaration_header);

		handleBodyDeclarations(node.bodyDeclarations());
		if (node.getModifiers() == 0)
			this.tm.firstTokenBefore(node.getName(), TokenNameAT).breakBefore();

		this.declarationModifierVisited = false;
		return true;
	}

	@Override
	public boolean visit(AnonymousClassDeclaration node) {
		if (node.getParent() instanceof EnumConstantDeclaration) {
			handleBracedCode(node, null, this.options.brace_position_for_enum_constant,
					this.options.indent_body_declarations_compare_to_enum_constant_header);
		} else {
			handleBracedCode(node, null, this.options.brace_position_for_anonymous_type_declaration,
					this.options.indent_body_declarations_compare_to_type_header);
		}
		handleBodyDeclarations(node.bodyDeclarations());
		return true;
	}

	@Override
	public boolean visit(MethodDeclaration node) {
		this.declarationModifierVisited = false;
		if (node.getBody() == null)
			return true;

		String bracePosition = node.isConstructor() ? this.options.brace_position_for_constructor_declaration
				: this.options.brace_position_for_method_declaration;
		handleBracedCode(node.getBody(), null, bracePosition, this.options.indent_statements_compare_to_body,
				this.options.blank_lines_at_beginning_of_method_body, this.options.blank_lines_at_end_of_method_body);

		return true;
	}

	@Override
	public boolean visit(Block node) {
		List<Statement> statements = node.statements();
		for (Statement statement : statements) {
			if (this.options.put_empty_statement_on_new_line || !(statement instanceof EmptyStatement))
				breakLineBefore(statement);
		}
		ASTNode parent = node.getParent();
		if (parent.getLength() == 0)
			return true; // this is a fake block created by parsing in statements mode
		if (parent instanceof MethodDeclaration)
			return true; // braces have been handled in #visit(MethodDeclaration)

		String bracePosition = this.options.brace_position_for_block;
		if (parent instanceof SwitchStatement) {
			List<Statement> siblings = ((SwitchStatement) parent).statements();
			int blockPosition = siblings.indexOf(node);
			boolean isFirstInCase = blockPosition > 0 && (siblings.get(blockPosition - 1) instanceof SwitchCase);
			if (isFirstInCase)
				bracePosition = this.options.brace_position_for_block_in_case;
		} else if (parent instanceof LambdaExpression) {
			bracePosition = this.options.brace_position_for_lambda_body;
		}
		handleBracedCode(node, null, bracePosition, this.options.indent_statements_compare_to_block,
				this.options.blank_lines_at_beginning_of_code_block, this.options.blank_lines_at_end_of_code_block);

		if (parent instanceof Block) {
			blankLinesAroundBlock(node, ((Block) parent).statements());
		} else if (parent instanceof Statement && parent.getParent() instanceof Block) {
			blankLinesAroundBlock(parent, ((Block) parent.getParent()).statements());
		}

		return true;
	}

	private void blankLinesAroundBlock(ASTNode blockStatement, List<ASTNode> siblings) {
		putBlankLinesBefore(blockStatement, this.options.blank_lines_before_code_block);
		if (!this.options.put_empty_statement_on_new_line) {
			int blockIndex = siblings.indexOf(blockStatement);
			if (blockIndex + 1 < siblings.size() && siblings.get(blockIndex + 1) instanceof EmptyStatement)
				return;
		}
		putBlankLinesAfter(this.tm.lastTokenIn(blockStatement, -1), this.options.blank_lines_after_code_block);
	}

	@Override
	public boolean visit(SwitchStatement node) {
		handleBracedCode(node, node.getExpression(), this.options.brace_position_for_switch,
				this.options.indent_switchstatements_compare_to_switch,
				this.options.blank_lines_at_beginning_of_code_block, this.options.blank_lines_at_end_of_code_block);

		List<Statement> statements = node.statements();
		doSwitchStatementsIndentation(node, statements);
		doSwitchStatementsLineBreaks(statements);

		if (node.getParent() instanceof Block)
			blankLinesAroundBlock(node, ((Block) node.getParent()).statements());

		return true;
	}

	@Override
	public boolean visit(SwitchExpression node) {
		handleBracedCode(node, node.getExpression(), this.options.brace_position_for_switch,
				this.options.indent_switchstatements_compare_to_switch,
				this.options.blank_lines_at_beginning_of_code_block, this.options.blank_lines_at_end_of_code_block);

		List<Statement> statements = node.statements();
		doSwitchStatementsIndentation(node, statements);
		doSwitchStatementsLineBreaks(statements);

		return true;
	}

	private void doSwitchStatementsIndentation(ASTNode switchNode, List<Statement> statements) {
		if (this.options.indent_switchstatements_compare_to_cases) {
			int nonBreakStatementEnd = -1;
			for (Statement statement : statements) {
				boolean isBreaking = isSwitchBreakingStatement(statement);
				if (isBreaking && !(statement instanceof Block))
					adjustEmptyLineAfter(this.tm.lastIndexIn(statement, -1), -1);
				if (statement instanceof SwitchCase) {
					if (nonBreakStatementEnd >= 0) {
						// indent only comments between previous and current statement
						this.tm.get(nonBreakStatementEnd + 1).indent();
						this.tm.firstTokenIn(statement, -1).unindent();
					}
				} else if (!(statement instanceof BreakStatement || statement instanceof YieldStatement
						|| statement instanceof Block)) {
					indent(statement);
				}
				nonBreakStatementEnd = isBreaking ? -1 : this.tm.lastIndexIn(statement, -1);
			}
			if (nonBreakStatementEnd >= 0) {
				// indent comments between last statement and closing brace
				this.tm.get(nonBreakStatementEnd + 1).indent();
				this.tm.lastTokenIn(switchNode, TokenNameRBRACE).unindent();
			}
		}
		if (this.options.indent_breaks_compare_to_cases) {
			for (Statement statement : statements) {
				if (statement instanceof BreakStatement || statement instanceof YieldStatement)
					indent(statement);
			}
		}
	}

	private void doSwitchStatementsLineBreaks(List<Statement> statements) {
		boolean arrowMode = statements.stream()
				.anyMatch(s -> s instanceof SwitchCase && ((SwitchCase) s).isSwitchLabeledRule());
		Statement previous = null;
		for (Statement statement : statements) {
			boolean skip = statement instanceof Block // will add break in visit(Block) if necessary
					|| (arrowMode && !(statement instanceof SwitchCase))
					|| (statement instanceof EmptyStatement && !this.options.put_empty_statement_on_new_line);
			if (!skip) {
				boolean newGroup = !arrowMode && statement instanceof SwitchCase && isSwitchBreakingStatement(previous);
				int blankLines = newGroup ? this.options.blank_lines_between_statement_groups_in_switch : 0;
				putBlankLinesBefore(statement, blankLines);
			}
			previous = statement;
		}
	}

	private boolean isSwitchBreakingStatement(Statement statement) {
		return statement instanceof BreakStatement || statement instanceof ReturnStatement
				|| statement instanceof ContinueStatement || statement instanceof ThrowStatement
				|| statement instanceof YieldStatement || statement instanceof Block;
	}

	@Override
	public boolean visit(DoStatement node) {
		Statement body = node.getBody();
		boolean sameLine = this.options.keep_simple_do_while_body_on_same_line;
		if (!sameLine)
			handleLoopBody(body);
		if (this.options.insert_new_line_before_while_in_do_statement
				|| (!(body instanceof Block) && !(body instanceof EmptyStatement) && !sameLine)) {
			Token whileToken = this.tm.firstTokenBefore(node.getExpression(), TokenNamewhile);
			whileToken.breakBefore();
		}
		return true;
	}

	@Override
	public boolean visit(LabeledStatement node) {
		if (this.options.insert_new_line_after_label)
			this.tm.firstTokenIn(node, TokenNameCOLON).breakAfter();
		return true;
	}

	@Override
	public boolean visit(ArrayInitializer node) {
		int openBraceIndex = this.tm.firstIndexIn(node, TokenNameLBRACE);
		int closeBraceIndex = this.tm.lastIndexIn(node, TokenNameRBRACE);

		boolean isEmpty = openBraceIndex + 1 == closeBraceIndex;
		if (isEmpty) {
			adjustEmptyLineAfter(openBraceIndex, this.options.continuation_indentation_for_array_initializer);
			closeBraceIndex = this.tm.lastIndexIn(node, TokenNameRBRACE);
		}

		Token openBraceToken = this.tm.get(openBraceIndex);
		Token closeBraceToken = this.tm.get(closeBraceIndex);

		if (!(node.getParent() instanceof ArrayInitializer)) {
			Token afterOpenBraceToken = this.tm.get(openBraceIndex + 1);
			for (int i = 0; i < this.options.continuation_indentation_for_array_initializer; i++) {
				afterOpenBraceToken.indent();
				closeBraceToken.unindent();
			}
		}

		if (!isEmpty || !this.options.keep_empty_array_initializer_on_one_line)
			handleBracePosition(openBraceToken, closeBraceIndex, this.options.brace_position_for_array_initializer);

		if (!isEmpty) {
			if (this.options.insert_new_line_after_opening_brace_in_array_initializer)
				openBraceToken.breakAfter();
			if (this.options.insert_new_line_before_closing_brace_in_array_initializer)
				closeBraceToken.breakBefore();
		}
		return true;
	}

	@Override
	public boolean visit(NormalAnnotation node) {
		handleAnnotation(node);
		return true;
	}

	@Override
	public boolean visit(SingleMemberAnnotation node) {
		handleAnnotation(node);
		return true;
	}

	@Override
	public boolean visit(MarkerAnnotation node) {
		handleAnnotation(node);
		return true;
	}

	@Override
	public boolean visit(VariableDeclarationStatement node) {
		this.declarationModifierVisited = false;
		return true;
	}

	@Override
	public boolean visit(SingleVariableDeclaration node) {
		this.declarationModifierVisited = false;
		if (node.getParent() instanceof MethodDeclaration) {
			// special case: annotations on parameters without modifiers should not be treated as type annotations
			this.declarationModifierVisited = (node.getModifiers() == 0);
		}
		return true;
	}

	@Override
	public boolean visit(VariableDeclarationExpression node) {
		this.declarationModifierVisited = false;
		return true;
	}

	@Override
	public boolean visit(FieldDeclaration node) {
		this.declarationModifierVisited = false;
		return true;
	}

	@Override
	public boolean visit(AnnotationTypeMemberDeclaration node) {
		this.declarationModifierVisited = false;
		return true;
	}

	@Override
	public boolean visit(EnumConstantDeclaration node) {
		this.declarationModifierVisited = false;
		return true;
	}

	@Override
	public boolean visit(Modifier node) {
		this.declarationModifierVisited = true;
		return true;
	}

	private void handleAnnotation(Annotation node) {
		ASTNode parentNode = node.getParent();
		boolean breakAfter = false;
		boolean isTypeAnnotation = this.declarationModifierVisited;
		if (isTypeAnnotation) {
			breakAfter = this.options.insert_new_line_after_type_annotation;
		} else if (parentNode instanceof PackageDeclaration) {
			breakAfter = this.options.insert_new_line_after_annotation_on_package;
		} else if (parentNode instanceof AbstractTypeDeclaration) {
			breakAfter = this.options.insert_new_line_after_annotation_on_type;
		} else if (parentNode instanceof EnumConstantDeclaration) {
			breakAfter = this.options.insert_new_line_after_annotation_on_enum_constant;
		} else if (parentNode instanceof FieldDeclaration) {
			breakAfter = this.options.insert_new_line_after_annotation_on_field;
		} else if (parentNode instanceof MethodDeclaration) {
			breakAfter = this.options.insert_new_line_after_annotation_on_method;
		} else if (parentNode instanceof AnnotationTypeMemberDeclaration) {
			breakAfter = this.options.insert_new_line_after_annotation_on_method
					&& ((AnnotationTypeMemberDeclaration) parentNode).getDefault() != node;
		} else if (parentNode instanceof VariableDeclarationStatement
				|| parentNode instanceof VariableDeclarationExpression) {
			breakAfter = this.options.insert_new_line_after_annotation_on_local_variable;
		} else if (parentNode instanceof SingleVariableDeclaration) {
			breakAfter = this.options.insert_new_line_after_annotation_on_parameter;
			if ((parentNode.getParent()) instanceof EnhancedForStatement)
				breakAfter = this.options.insert_new_line_after_annotation_on_local_variable;
		}
		if (breakAfter)
			this.tm.lastTokenIn(node, -1).breakAfter();
	}

	@Override
	public boolean visit(WhileStatement node) {
		if (!this.options.keep_simple_while_body_on_same_line)
			handleLoopBody(node.getBody());
		return true;
	}

	@Override
	public boolean visit(ForStatement node) {
		if (!this.options.keep_simple_for_body_on_same_line)
			handleLoopBody(node.getBody());
		return true;
	}

	@Override
	public boolean visit(EnhancedForStatement node) {
		if (!this.options.keep_simple_for_body_on_same_line)
			handleLoopBody(node.getBody());
		return true;
	}

	private void handleLoopBody(Statement body) {
		if (body instanceof Block)
			return;
		if (body instanceof EmptyStatement && !this.options.put_empty_statement_on_new_line
				&& !(body.getParent() instanceof IfStatement))
			return;
		breakLineBefore(body);
		adjustEmptyLineAfter(this.tm.lastIndexIn(body, -1), -1);
		indent(body);
	}

	@Override
	public boolean visit(IfStatement node) {
		Statement elseNode = node.getElseStatement();
		Statement thenNode = node.getThenStatement();
		if (elseNode != null) {
			if (this.options.insert_new_line_before_else_in_if_statement || !(thenNode instanceof Block))
				this.tm.firstTokenBefore(elseNode, TokenNameelse).breakBefore();

			boolean keepElseOnSameLine = (this.options.keep_else_statement_on_same_line)
					|| (this.options.compact_else_if && (elseNode instanceof IfStatement));
			if (!keepElseOnSameLine)
				handleLoopBody(elseNode);
		}

		boolean keepThenOnSameLine = this.options.keep_then_statement_on_same_line
				|| (this.options.keep_simple_if_on_one_line && elseNode == null);
		if (!keepThenOnSameLine)
			handleLoopBody(thenNode);

		return true;
	}

	@Override
	public boolean visit(TryStatement node) {
		if (node.getFinally() != null && this.options.insert_new_line_before_finally_in_try_statement) {
			this.tm.firstTokenBefore(node.getFinally(), TokenNamefinally).breakBefore();
		}
		return true;
	}

	@Override
	public boolean visit(CatchClause node) {
		if (this.options.insert_new_line_before_catch_in_try_statement)
			breakLineBefore(node);
		return true;
	}

//{ObjectTeams: more visits:
	@Override
	public boolean visit(RoleTypeDeclaration node) {
		return visit((TypeDeclaration)node);
	}
	@Override
	public boolean visit(CalloutMappingDeclaration node) {
		if (node.hasParameterMapping()) {
			for (Object pMap : node.getParameterMappings())
				breakLineBefore((ASTNode) pMap);
			String bracePosition = this.options.brace_position_for_method_declaration;
			handleBracedCode(node, null, bracePosition, this.options.indent_statements_compare_to_block);
		}
		return true;
	}
	@Override
	public boolean visit(CallinMappingDeclaration node) {
		GuardPredicateDeclaration predicate = node.getGuardPredicate();
		if (predicate != null) {
			this.tm.firstTokenIn(node.getGuardPredicate(), predicate.isBase() ? TokenNamebase : TokenNamewhen).breakBefore();
			indent(node.getGuardPredicate());
		}

		if (node.hasParameterMapping()) {
			for (Object pMap : node.getParameterMappings())
				breakLineBefore((ASTNode) pMap);
			String bracePosition = this.options.brace_position_for_method_declaration;
			handleBracedCode(node, null, bracePosition, this.options.indent_statements_compare_to_block);
		}
		return true;
	}
	@Override
	public boolean visit(WithinStatement node) { // like while
		handleLoopBody(node.getBody());
		return true;
	}
// SH}

	@Override
	public boolean visit(ModuleDeclaration node) {
		// using settings for type declaration and fields for now, add new settings if necessary
		breakLineBefore(node);
		List<ModuleDirective> statements = node.moduleStatements();
		handleBracedCode(node, node.getName(), this.options.brace_position_for_type_declaration,
				this.options.indent_body_declarations_compare_to_type_header,
				statements.isEmpty() ? 0 : this.options.blank_lines_before_first_class_body_declaration,
				statements.isEmpty() ? 0 : this.options.blank_lines_after_last_class_body_declaration);

		ModuleDirective previous = null;
		for (ModuleDirective statement : statements) {
			if (previous != null) {
				boolean cameChunk = previous.getClass().equals(statement.getClass());
				putBlankLinesBefore(statement,
						cameChunk ? this.options.blank_lines_before_field : this.options.blank_lines_before_new_chunk);
			}
			previous = statement;
		}

		this.declarationModifierVisited = false;
		return true;
	}

	private void breakLineBefore(ASTNode node) {
		this.tm.firstTokenIn(node, -1).breakBefore();
	}

	private void putBlankLinesBefore(ASTNode node, int linesCount) {
		int index = this.tm.firstIndexIn(node, -1);
		while (index > 0 && this.tm.get(index - 1).tokenType == TokenNameCOMMENT_JAVADOC)
			index--;
		putBlankLinesBefore(this.tm.get(index), linesCount);
	}

	private void putBlankLinesBefore(Token token, int linesCount) {
		if (linesCount >= 0) {
			token.putLineBreaksBefore(linesCount + 1);
		} else {
			token.putLineBreaksBefore(~linesCount + 1);
			token.setPreserveLineBreaksBefore(false);
		}
	}

	private void putBlankLinesAfter(Token token, int linesCount) {
		if (linesCount >= 0) {
			token.putLineBreaksAfter(linesCount + 1);
		} else {
			token.putLineBreaksAfter(~linesCount + 1);
			token.setPreserveLineBreaksAfter(false);
		}
	}

	private void handleBracedCode(ASTNode node, ASTNode nodeBeforeOpenBrace, String bracePosition, boolean indentBody) {
		handleBracedCode(node, nodeBeforeOpenBrace, bracePosition, indentBody, 0, 0);
	}
	
	private void handleBracedCode(ASTNode node, ASTNode nodeBeforeOpenBrace, String bracePosition, boolean indentBody,
			int blankLinesAfterOpeningBrace, int blankLinesBeforeClosingBrace) {
		int openBraceIndex = nodeBeforeOpenBrace == null
				? this.tm.firstIndexIn(node, TokenNameLBRACE)
				: this.tm.firstIndexAfter(nodeBeforeOpenBrace, TokenNameLBRACE);
		int closeBraceIndex = this.tm.lastIndexIn(node, TokenNameRBRACE);
		Token openBraceToken = this.tm.get(openBraceIndex);
		Token closeBraceToken = this.tm.get(closeBraceIndex);
		handleBracePosition(openBraceToken, closeBraceIndex, bracePosition);

		putBlankLinesAfter(openBraceToken, blankLinesAfterOpeningBrace);
		putBlankLinesBefore(closeBraceToken, blankLinesBeforeClosingBrace);

		if (indentBody) {
			adjustEmptyLineAfter(openBraceIndex, 1);
			this.tm.get(openBraceIndex + 1).indent();
			closeBraceToken.unindent();
		}
	}

	private void handleBracePosition(Token openBraceToken, int closeBraceIndex, String bracePosition) {
		if (bracePosition.equals(DefaultCodeFormatterConstants.NEXT_LINE)) {
			openBraceToken.breakBefore();
		} else if (bracePosition.equals(DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED)) {
			openBraceToken.breakBefore();
			openBraceToken.indent();
			if (closeBraceIndex + 1 < this.tm.size())
				this.tm.get(closeBraceIndex + 1).unindent();
		} else if (bracePosition.equals(DefaultCodeFormatterConstants.NEXT_LINE_ON_WRAP)) {
			openBraceToken.setNextLineOnWrap();
		}
	}

	private void adjustEmptyLineAfter(int tokenIndex, int indentationAdjustment) {
		if (tokenIndex + 1 >= this.tm.size())
			return;
		Token token = this.tm.get(tokenIndex);
		Token next = this.tm.get(tokenIndex + 1);
		if (this.tm.countLineBreaksBetween(token, next) < 2 || !this.options.indent_empty_lines)
			return;

		next.setEmptyLineIndentAdjustment(indentationAdjustment * this.options.indentation_size);
	}

	private void indent(ASTNode node) {
		int startIndex = this.tm.firstIndexIn(node, -1);
		while (startIndex > 0 && this.tm.get(startIndex - 1).isComment())
			startIndex--;
		this.tm.get(startIndex).indent();
		int lastIndex = this.tm.lastIndexIn(node, -1);
		if (lastIndex + 1 < this.tm.size())
			this.tm.get(lastIndex + 1).unindent();
	}

	public void finishUp() {
		// the visits only noted where indents increase and decrease,
		// now prepare actual indent values
		int currentIndent = this.options.initial_indentation_level;
		for (Token token : this.tm) {
			currentIndent += token.getIndent();
			token.setIndent(currentIndent * this.options.indentation_size);
		}
	}
}
