/*******************************************************************************
 * Copyright (c) 2000, 2016 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
 * $Id: ASTRewriteFormatter.java 22741 2009-10-13 22:23:05Z stephan $
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Fraunhofer FIRST - extended API and implementation
 *     Technical University Berlin - extended API and implementation
 *******************************************************************************/
package org.eclipse.jdt.internal.core.dom.rewrite;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import org.eclipse.core.runtime.Assert;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.ToolFactory;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.Annotation;
import org.eclipse.jdt.core.dom.Block;
import org.eclipse.jdt.core.dom.BodyDeclaration;
import org.eclipse.jdt.core.dom.Expression;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.Statement;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.jdt.core.formatter.CodeFormatter;
import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants;
import org.eclipse.jdt.core.formatter.IndentManipulation;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.BadPositionCategoryException;
import org.eclipse.jface.text.DefaultPositionUpdater;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.Position;
import org.eclipse.text.edits.DeleteEdit;
import org.eclipse.text.edits.InsertEdit;
import org.eclipse.text.edits.MultiTextEdit;
import org.eclipse.text.edits.ReplaceEdit;
import org.eclipse.text.edits.TextEdit;

@SuppressWarnings({"rawtypes", "unchecked"})
public final class ASTRewriteFormatter {

	public static class NodeMarker extends Position {
		public Object data;
	}

	private class ExtendedFlattener extends ASTRewriteFlattener {

		private ArrayList positions;

		public ExtendedFlattener(RewriteEventStore store) {
			super(store);
			this.positions= new ArrayList();
		}

		/* (non-Javadoc)
		 * @see org.eclipse.jdt.core.dom.ASTVisitor#preVisit(ASTNode)
		 */
		public void preVisit(ASTNode node) {
			Object trackData= getEventStore().getTrackedNodeData(node);
			if (trackData != null) {
				addMarker(trackData, this.result.length(), 0);
			}
			Object placeholderData= getPlaceholders().getPlaceholderData(node);
			if (placeholderData != null) {
				addMarker(placeholderData, this.result.length(), 0);
			}
		}

		/* (non-Javadoc)
		 * @see org.eclipse.jdt.core.dom.ASTVisitor#postVisit(ASTNode)
		 */
		public void postVisit(ASTNode node) {
			Object placeholderData= getPlaceholders().getPlaceholderData(node);
			if (placeholderData != null) {
				fixupLength(placeholderData, this.result.length());
			}
			Object trackData= getEventStore().getTrackedNodeData(node);
			if (trackData != null) {
				fixupLength(trackData, this.result.length());
			}
		}

		/* (non-Javadoc)
		 * @see org.eclipse.jdt.internal.corext.dom.ASTRewriteFlattener#visit(org.eclipse.jdt.core.dom.Block)
		 */
		public boolean visit(Block node) {
			if (getPlaceholders().isCollapsed(node)) {
				visitList(node, Block.STATEMENTS_PROPERTY, null);
				return false;
			}
			return super.visit(node);
		}

		private NodeMarker addMarker(Object annotation, int startOffset, int length) {
			NodeMarker marker= new NodeMarker();
			marker.offset= startOffset;
			marker.length= length;
			marker.data= annotation;
			this.positions.add(marker);
			return marker;
		}

		private void fixupLength(Object data, int endOffset) {
			for (int i= this.positions.size()-1; i >= 0 ; i--) {
				NodeMarker marker= (NodeMarker) this.positions.get(i);
				if (marker.data == data) {
					marker.length= endOffset - marker.offset;
					return;
				}
			}
		}

		public NodeMarker[] getMarkers() {
			return (NodeMarker[]) this.positions.toArray(new NodeMarker[this.positions.size()]);
		}
	}

	private final String lineDelimiter;
	private final int tabWidth;
	private final int indentWidth;

	private final NodeInfoStore placeholders;
	private final RewriteEventStore eventStore;

	private final Map options;


	public ASTRewriteFormatter(NodeInfoStore placeholders, RewriteEventStore eventStore, Map options, String lineDelimiter) {
		this.placeholders= placeholders;
		this.eventStore= eventStore;
	
		this.options= options == null ? JavaCore.getOptions() : (Map) new HashMap(options);
		this.options.put(
				DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_RESOURCES_IN_TRY,
				DefaultCodeFormatterConstants.createAlignmentValue(true, DefaultCodeFormatterConstants.WRAP_NEXT_PER_LINE, DefaultCodeFormatterConstants.INDENT_DEFAULT));

		this.lineDelimiter= lineDelimiter;
	
		this.tabWidth= IndentManipulation.getTabWidth(options);
		this.indentWidth= IndentManipulation.getIndentWidth(options);
	}



	public NodeInfoStore getPlaceholders() {
		return this.placeholders;
	}

	public RewriteEventStore getEventStore() {
		return this.eventStore;
	}

	public int getTabWidth() {
		return this.tabWidth;
	}

	public int getIndentWidth() {
		return this.indentWidth;
	}

	public String getLineDelimiter() {
		return this.lineDelimiter;
	}

	/**
	 * Returns the string accumulated in the visit formatted using the default formatter.
	 * Updates the existing node's positions.
	 *
	 * @param node The node to flatten.
	 * @param initialIndentationLevel The initial indentation level.
	 * @param resultingMarkers Resulting the updated NodeMarkers.
	 * @return Returns the serialized and formatted code.
	 */
	public String getFormattedResult(ASTNode node, int initialIndentationLevel, Collection resultingMarkers) {

		ExtendedFlattener flattener= new ExtendedFlattener(this.eventStore);
		node.accept(flattener);

		NodeMarker[] markers= flattener.getMarkers();
		for (int i= 0; i < markers.length; i++) {
			resultingMarkers.add(markers[i]); // add to result
		}

		String unformatted= flattener.getResult();
		TextEdit edit= formatNode(node, unformatted, initialIndentationLevel);
		if (edit == null) {
		    if (initialIndentationLevel > 0) {
		        // at least correct the indent
		        String indentString = createIndentString(initialIndentationLevel);
				ReplaceEdit[] edits = IndentManipulation.getChangeIndentEdits(unformatted, 0, this.tabWidth, this.indentWidth, indentString);
				edit= new MultiTextEdit();
				edit.addChild(new InsertEdit(0, indentString));
				edit.addChildren(edits);
		    } else {
		       return unformatted;
		    }
		}
		return evaluateFormatterEdit(unformatted, edit, markers);
	}

    public String createIndentString(int indentationUnits) {
    	return ToolFactory.createCodeFormatter(this.options).createIndentationString(indentationUnits);
    }

	public String getIndentString(String currentLine) {
		return IndentManipulation.extractIndentString(currentLine, this.tabWidth, this.indentWidth);
	}

	public String changeIndent(String code, int codeIndentLevel, String newIndent) {
		return IndentManipulation.changeIndent(code, codeIndentLevel, this.tabWidth, this.indentWidth, newIndent, this.lineDelimiter);
	}

	public int computeIndentUnits(String line) {
		return IndentManipulation.measureIndentUnits(line, this.tabWidth, this.indentWidth);
	}

	/**
	 * Evaluates the edit on the given string.
	 * @param string The string to format
	 * @param edit The edit resulted from the code formatter
	 * @param positions Positions to update or <code>null</code>.
	 * @return The formatted string
	 * @throws IllegalArgumentException If the positions are not inside the string, a
	 *  IllegalArgumentException is thrown.
	 */
	public static String evaluateFormatterEdit(String string, TextEdit edit, Position[] positions) {
		try {
			Document doc= createDocument(string, positions);
			edit.apply(doc, 0);
			if (positions != null) {
				for (int i= 0; i < positions.length; i++) {
					Assert.isTrue(!positions[i].isDeleted, "Position got deleted"); //$NON-NLS-1$
				}
			}
			return doc.get();
		} catch (BadLocationException e) {
			//JavaPlugin.log(e); // bug in the formatter
			Assert.isTrue(false, "Fromatter created edits with wrong positions: " + e.getMessage()); //$NON-NLS-1$
		}
		return null;
	}

	public TextEdit formatString(int kind, String string, int offset, int length, int indentationLevel) {
		return ToolFactory.createCodeFormatter(this.options).format(kind, string, offset, length, indentationLevel, this.lineDelimiter);
	}

	/**
	 * Creates edits that describe how to format the given string. Returns <code>null</code> if the code could not be formatted for the given kind.
	 * @param node Node describing the type of the string
	 * @param str The unformatted string
	 * @param indentationLevel
	 * @return Returns the edit representing the result of the formatter
	 * @throws IllegalArgumentException If the offset and length are not inside the string, a
	 *  IllegalArgumentException is thrown.
	 */
	private TextEdit formatNode(ASTNode node, String str, int indentationLevel) {
		int code;
		String prefix= ""; //$NON-NLS-1$
		String suffix= ""; //$NON-NLS-1$
//{ObjectTeams: check code flavour:
		this.options.put(CompilerOptions.OPTION_AllowScopedKeywords, isOTJCode(node)?CompilerOptions.DISABLED:CompilerOptions.ENABLED);
		// FIXME(SH): if not recognizable as OTJCode set OPTION_PureJavaOnly to ENABLED??
// SH}
		if (node instanceof Statement) {
			code= CodeFormatter.K_STATEMENTS;
			if (node.getNodeType() == ASTNode.SWITCH_CASE) {
				prefix= "switch(1) {"; //$NON-NLS-1$
				suffix= "}"; //$NON-NLS-1$
				code= CodeFormatter.K_STATEMENTS;
			}
		} else if (node instanceof Expression && node.getNodeType() != ASTNode.VARIABLE_DECLARATION_EXPRESSION) {
//{ObjectTeams: tells the formatter to format a single parameter mapping. It is not handled by the formatExpression method !!
		  if (node.getNodeType() == ASTNode.PARAMETER_MAPPING) {
			code = CodeFormatter.K_PARAMETER_MAPPING;
		  } else
//jsv}
			if (node instanceof Annotation) {
				suffix= "\nclass A {}"; //$NON-NLS-1$
				code= CodeFormatter.K_COMPILATION_UNIT;
			} else {
				code= CodeFormatter.K_EXPRESSION;
			}
		} else if (node instanceof BodyDeclaration) {
			code= CodeFormatter.K_CLASS_BODY_DECLARATIONS;
		} else {
			switch (node.getNodeType()) {
				case ASTNode.ARRAY_TYPE:
				case ASTNode.PARAMETERIZED_TYPE:
				case ASTNode.PRIMITIVE_TYPE:
				case ASTNode.QUALIFIED_TYPE:
				case ASTNode.SIMPLE_TYPE:
					prefix= "void m(final "; //$NON-NLS-1$
					suffix= " x);"; //$NON-NLS-1$
					code= CodeFormatter.K_CLASS_BODY_DECLARATIONS;
					break;
				case ASTNode.WILDCARD_TYPE:
					prefix= "A<"; //$NON-NLS-1$
					suffix= "> x;"; //$NON-NLS-1$
					code= CodeFormatter.K_CLASS_BODY_DECLARATIONS;
					break;
				case ASTNode.COMPILATION_UNIT:
					code= CodeFormatter.K_COMPILATION_UNIT;
					break;
				case ASTNode.VARIABLE_DECLARATION_EXPRESSION:
					suffix= ";"; //$NON-NLS-1$
					code= CodeFormatter.K_STATEMENTS;
					break;
				case ASTNode.SINGLE_VARIABLE_DECLARATION:
					prefix= "void m("; //$NON-NLS-1$
					suffix= ");"; //$NON-NLS-1$
					code= CodeFormatter.K_CLASS_BODY_DECLARATIONS;
					break;
				case ASTNode.VARIABLE_DECLARATION_FRAGMENT:
					prefix= "A "; //$NON-NLS-1$
					suffix= ";"; //$NON-NLS-1$
					code= CodeFormatter.K_STATEMENTS;
					break;
				case ASTNode.PACKAGE_DECLARATION:
				case ASTNode.IMPORT_DECLARATION:
					suffix= "\nclass A {}"; //$NON-NLS-1$
					code= CodeFormatter.K_COMPILATION_UNIT;
					break;
				case ASTNode.JAVADOC:
					suffix= "\nclass A {}"; //$NON-NLS-1$
					code= CodeFormatter.K_COMPILATION_UNIT;
					break;
				case ASTNode.CATCH_CLAUSE:
					prefix= "try {}"; //$NON-NLS-1$
					code= CodeFormatter.K_STATEMENTS;
					break;
				case ASTNode.ANONYMOUS_CLASS_DECLARATION:
					prefix= "new A()"; //$NON-NLS-1$
					suffix= ";"; //$NON-NLS-1$
					code= CodeFormatter.K_STATEMENTS;
					break;
				case ASTNode.MEMBER_VALUE_PAIR:
					prefix= "@Author("; //$NON-NLS-1$
					suffix= ") class x {}"; //$NON-NLS-1$
					code= CodeFormatter.K_COMPILATION_UNIT;
					break;
				case ASTNode.MODIFIER:
					suffix= " class x {}"; //$NON-NLS-1$
					code= CodeFormatter.K_COMPILATION_UNIT;
					break;
				case ASTNode.TYPE_PARAMETER:
					prefix= "class X<"; //$NON-NLS-1$
					suffix= "> {}"; //$NON-NLS-1$
					code= CodeFormatter.K_COMPILATION_UNIT;
					break;
				case ASTNode.MEMBER_REF:
				case ASTNode.METHOD_REF:
				case ASTNode.METHOD_REF_PARAMETER:
				case ASTNode.TAG_ELEMENT:
				case ASTNode.TEXT_ELEMENT:
					// javadoc formatting disabled due to bug 93644
					return null;

//				wiat for bug 93644
//				case ASTNode.MEMBER_REF:
//				case ASTNode.METHOD_REF:
//					prefix= "/**\n * @see ";
//					suffix= "\n*/";
//					code= CodeFormatter.K_JAVA_DOC;
//					break;
//				case ASTNode.METHOD_REF_PARAMETER:
//					prefix= "/**\n * @see A#foo(";
//					suffix= ")\n*/";
//					code= CodeFormatter.K_JAVA_DOC;
//					break;
//				case ASTNode.TAG_ELEMENT:
//				case ASTNode.TEXT_ELEMENT:
//					prefix= "/**\n * ";
//					suffix= "\n*/";
//					code= CodeFormatter.K_JAVA_DOC;
//					break;
				default:
					//Assert.isTrue(false, "Node type not covered: " + node.getClass().getName());
					return null;
			}
		}

		String concatStr= prefix + str + suffix;
		TextEdit edit= formatString(code, concatStr, prefix.length(), str.length(), indentationLevel);

		if (prefix.length() > 0) {
			edit= shifEdit(edit, prefix.length());
		}
		return edit;
	}

//{ObjectTeams: needed to configure the scanner:
	private boolean isOTJCode(ASTNode node) {
		while (node != null && node.getNodeType() != ASTNode.TYPE_DECLARATION) {
			switch (node.getNodeType()) {
			case ASTNode.ROLE_TYPE_DECLARATION:
			case ASTNode.CALLOUT_MAPPING_DECLARATION:
			case ASTNode.CALLIN_MAPPING_DECLARATION:
			case ASTNode.PARAMETER_MAPPING:
				return true;
			case ASTNode.METHOD_DECLARATION:
				if ((((MethodDeclaration)node).getModifiers() & ExtraCompilerModifiers.AccCallin) != 0)
					return true;
			}
			node= node.getParent();
		}
		if (node != null) {
			TypeDeclaration type = (TypeDeclaration)node;
			return type.isRole() || type.isTeam();
		}
		return false;
	}
// SH}

	private static TextEdit shifEdit(TextEdit oldEdit, int diff) {
		TextEdit newEdit;
		if (oldEdit instanceof ReplaceEdit) {
			ReplaceEdit edit= (ReplaceEdit) oldEdit;
			newEdit= new ReplaceEdit(edit.getOffset() - diff, edit.getLength(), edit.getText());
		} else if (oldEdit instanceof InsertEdit) {
			InsertEdit edit= (InsertEdit) oldEdit;
			newEdit= new InsertEdit(edit.getOffset() - diff,  edit.getText());
		} else if (oldEdit instanceof DeleteEdit) {
			DeleteEdit edit= (DeleteEdit) oldEdit;
			newEdit= new DeleteEdit(edit.getOffset() - diff,  edit.getLength());
		} else if (oldEdit instanceof MultiTextEdit) {
			newEdit= new MultiTextEdit();
		} else {
			return null; // not supported
		}
		TextEdit[] children= oldEdit.getChildren();
		for (int i= 0; i < children.length; i++) {
			TextEdit shifted= shifEdit(children[i], diff);
			if (shifted != null) {
				newEdit.addChild(shifted);
			}
		}
		return newEdit;
	}

	private static Document createDocument(String string, Position[] positions) throws IllegalArgumentException {
		Document doc= new Document(string);
		try {
			if (positions != null) {
				final String POS_CATEGORY= "myCategory"; //$NON-NLS-1$

				doc.addPositionCategory(POS_CATEGORY);
				doc.addPositionUpdater(new DefaultPositionUpdater(POS_CATEGORY) {
					protected boolean notDeleted() {
						int start= this.fOffset;
						int end= start + this.fLength;
						if (start < this.fPosition.offset && (this.fPosition.offset + this.fPosition.length < end)) {
							this.fPosition.offset= end; // deleted positions: set to end of remove
							return false;
						}
						return true;
					}
				});
				for (int i= 0; i < positions.length; i++) {
					try {
						doc.addPosition(POS_CATEGORY, positions[i]);
					} catch (BadLocationException e) {
						throw new IllegalArgumentException("Position outside of string. offset: " + positions[i].offset + ", length: " + positions[i].length + ", string size: " + string.length(), e);   //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
					}
				}
			}
		} catch (BadPositionCategoryException cannotHappen) {
			// can not happen: category is correctly set up
		}
		return doc;
	}



    public static interface Prefix {
		String getPrefix(int indent);
	}

	public static interface BlockContext {
		String[] getPrefixAndSuffix(int indent, ASTNode node, RewriteEventStore events);
	}

	public static class ConstPrefix implements Prefix {
		private String prefix;

		public ConstPrefix(String prefix) {
			this.prefix= prefix;
		}

		public String getPrefix(int indent) {
			return this.prefix;
		}
	}

	private class FormattingPrefix implements Prefix {
		private int kind;
		private String string;
		private int start;
		private int length;

		public FormattingPrefix(String string, String sub, int kind) {
			this.start= string.indexOf(sub);
			this.length= sub.length();
			this.string= string;
			this.kind= kind;
		}

		public String getPrefix(int indent) {
			Position pos= new Position(this.start, this.length);
			String str= this.string;
			TextEdit res= formatString(this.kind, str, 0, str.length(), indent);
			if (res != null) {
				str= evaluateFormatterEdit(str, res, new Position[] { pos });
			}
			return str.substring(pos.offset + 1, pos.offset + pos.length - 1);
		}
	}

	private class BlockFormattingPrefix implements BlockContext {
		private String prefix;
		private int start;

		public BlockFormattingPrefix(String prefix, int start) {
			this.start= start;
			this.prefix= prefix;
		}

		public String[] getPrefixAndSuffix(int indent, ASTNode node, RewriteEventStore events) {
			String nodeString= ASTRewriteFlattener.asString(node, events);
			String str= this.prefix + nodeString;
			Position pos= new Position(this.start, this.prefix.length() + 1 - this.start);

			TextEdit res= formatString(CodeFormatter.K_STATEMENTS, str, 0, str.length(), indent);
			if (res != null) {
				str= evaluateFormatterEdit(str, res, new Position[] { pos });
			}
			return new String[] { str.substring(pos.offset + 1, pos.offset + pos.length - 1), ""}; //$NON-NLS-1$
		}
	}

	private class BlockFormattingPrefixSuffix implements BlockContext {
		private String prefix;
		private String suffix;
		private int start;

		public BlockFormattingPrefixSuffix(String prefix, String suffix, int start) {
			this.start= start;
			this.suffix= suffix;
			this.prefix= prefix;
		}

		public String[] getPrefixAndSuffix(int indent, ASTNode node, RewriteEventStore events) {
			String nodeString= ASTRewriteFlattener.asString(node, events);
			int nodeStart= this.prefix.length();
			int nodeEnd= nodeStart + nodeString.length() - 1;

			String str= this.prefix + nodeString + this.suffix;

			Position pos1= new Position(this.start, nodeStart + 1 - this.start);
			Position pos2= new Position(nodeEnd, 2);

			TextEdit res= formatString(CodeFormatter.K_STATEMENTS, str, 0, str.length(), indent);
			if (res != null) {
				str= evaluateFormatterEdit(str, res, new Position[] { pos1, pos2 });
			}
			return new String[] {
				str.substring(pos1.offset + 1, pos1.offset + pos1.length - 1),
				str.substring(pos2.offset + 1, pos2.offset + pos2.length - 1)
			};
		}
	}

	public final static Prefix NONE= new ConstPrefix(""); //$NON-NLS-1$
	public final static Prefix SPACE= new ConstPrefix(" "); //$NON-NLS-1$
	public final static Prefix ASSERT_COMMENT= new ConstPrefix(" : "); //$NON-NLS-1$

	public final Prefix VAR_INITIALIZER= new FormattingPrefix("A a={};", "a={" , CodeFormatter.K_STATEMENTS); //$NON-NLS-1$ //$NON-NLS-2$
	public final Prefix METHOD_BODY= new FormattingPrefix("void a() {}", ") {" , CodeFormatter.K_CLASS_BODY_DECLARATIONS); //$NON-NLS-1$ //$NON-NLS-2$
	public final Prefix FINALLY_BLOCK= new FormattingPrefix("try {} finally {}", "} finally {", CodeFormatter.K_STATEMENTS); //$NON-NLS-1$ //$NON-NLS-2$
	public final Prefix CATCH_BLOCK= new FormattingPrefix("try {} catch(Exception e) {}", "} c" , CodeFormatter.K_STATEMENTS); //$NON-NLS-1$ //$NON-NLS-2$
	public final Prefix ANNOT_MEMBER_DEFAULT= new FormattingPrefix("String value() default 1;", ") default 1" , CodeFormatter.K_CLASS_BODY_DECLARATIONS); //$NON-NLS-1$ //$NON-NLS-2$
	public final Prefix ENUM_BODY_START= new FormattingPrefix("enum E { A(){void foo(){}} }", "){v" , CodeFormatter.K_COMPILATION_UNIT); //$NON-NLS-1$ //$NON-NLS-2$
	public final Prefix ENUM_BODY_END= new FormattingPrefix("enum E { A(){void foo(){ }}, B}", "}}," , CodeFormatter.K_COMPILATION_UNIT); //$NON-NLS-1$ //$NON-NLS-2$
	public final Prefix WILDCARD_EXTENDS= new FormattingPrefix("A<? extends B> a;", "? extends B" , CodeFormatter.K_CLASS_BODY_DECLARATIONS); //$NON-NLS-1$ //$NON-NLS-2$
	public final Prefix WILDCARD_SUPER= new FormattingPrefix("A<? super B> a;", "? super B" , CodeFormatter.K_CLASS_BODY_DECLARATIONS); //$NON-NLS-1$ //$NON-NLS-2$

	public final Prefix FIRST_ENUM_CONST= new FormattingPrefix("enum E { X;}", "{ X" , CodeFormatter.K_COMPILATION_UNIT); //$NON-NLS-1$ //$NON-NLS-2$
	public final Prefix ANNOTATION_SEPARATION= new FormattingPrefix("@A @B class C {}", "A @" , CodeFormatter.K_COMPILATION_UNIT); //$NON-NLS-1$ //$NON-NLS-2$
	public final Prefix PARAM_ANNOTATION_SEPARATION= new FormattingPrefix("void foo(@A @B C p) { }", "A @" , CodeFormatter.K_CLASS_BODY_DECLARATIONS); //$NON-NLS-1$ //$NON-NLS-2$
	public final Prefix LOCAL_ANNOTATION_SEPARATION= new FormattingPrefix("@A @B C p;", "A @" , CodeFormatter.K_STATEMENTS); //$NON-NLS-1$ //$NON-NLS-2$
	public final Prefix TYPE_ANNOTATION_SEPARATION= new FormattingPrefix("C<@A @B D> l;", "A @" , CodeFormatter.K_STATEMENTS); //$NON-NLS-1$ //$NON-NLS-2$
	public final Prefix VARARGS= new FormattingPrefix("void foo(A ... a) { }", "A ." , CodeFormatter.K_CLASS_BODY_DECLARATIONS); //$NON-NLS-1$ //$NON-NLS-2$
	public final Prefix TRY_RESOURCES = new FormattingPrefix("try (A a = new A(); B b = new B()) {}", "; B" , CodeFormatter.K_STATEMENTS); //$NON-NLS-1$ //$NON-NLS-2$
	public final Prefix TRY_RESOURCES_PAREN = new FormattingPrefix("try (A a = new A(); B b = new B()) {}", "y (" , CodeFormatter.K_STATEMENTS); //$NON-NLS-1$ //$NON-NLS-2$
	
	public final BlockContext IF_BLOCK_WITH_ELSE= new BlockFormattingPrefixSuffix("if (true)", "else{}", 8); //$NON-NLS-1$ //$NON-NLS-2$
	public final BlockContext IF_BLOCK_NO_ELSE= new BlockFormattingPrefix("if (true)", 8); //$NON-NLS-1$
	public final BlockContext ELSE_AFTER_STATEMENT= new BlockFormattingPrefix("if (true) foo();else ", 15); //$NON-NLS-1$
	public final BlockContext ELSE_AFTER_BLOCK= new BlockFormattingPrefix("if (true) {}else ", 11); //$NON-NLS-1$

	public final BlockContext FOR_BLOCK= new BlockFormattingPrefix("for (;;) ", 7); //$NON-NLS-1$
	public final BlockContext WHILE_BLOCK= new BlockFormattingPrefix("while (true)", 11); //$NON-NLS-1$
	public final BlockContext DO_BLOCK= new BlockFormattingPrefixSuffix("do ", "while (true);", 1); //$NON-NLS-1$ //$NON-NLS-2$

}
