/*******************************************************************************
 * Copyright (c) 2000, 2011 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
 *
 * This is an implementation of an early-draft specification developed under the Java
 * Community Process (JCP) and is made available for testing and evaluation purposes
 * only. The code is not compatible with any specification of the JCP.
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.jdt.internal.ui.text;

import org.eclipse.core.runtime.Assert;

import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;

import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants;

import org.eclipse.jdt.internal.corext.util.CodeFormatterUtil;

import org.eclipse.jdt.internal.ui.JavaPlugin;


/**
 * Uses the {@link org.eclipse.jdt.internal.ui.text.JavaHeuristicScanner} to
 * get the indentation level for a certain position in a document.
 *
 * <p>
 * An instance holds some internal position in the document and is therefore
 * not threadsafe.
 * </p>
 *
 * @since 3.0
 */
public final class JavaIndenter {

	/**
	 * The JDT Core preferences.
	 * @since 3.2
	 */
	private final class CorePrefs {
		final boolean prefUseTabs;
		final int prefTabSize;
		final int prefIndentationSize;
		final boolean prefArrayDimensionsDeepIndent;
		final int prefArrayIndent;
		final boolean prefArrayDeepIndent;
		final boolean prefTernaryDeepAlign;
		final int prefTernaryIndent;
		final int prefCaseIndent;
		final int prefCaseBlockIndent;
		final int prefSimpleIndent;
		final int prefBracketIndent;
		final boolean prefMethodDeclDeepIndent;
		final int prefMethodDeclIndent;
		final boolean prefMethodCallDeepIndent;
		final int prefMethodCallIndent;
		final boolean prefParenthesisDeepIndent;
		final int prefParenthesisIndent;
		final int prefBlockIndent;
		final int prefMethodBodyIndent;
		final int prefTypeIndent;
		final boolean prefIndentBracesForBlocks;
		final boolean prefIndentBracesForArrays;
		final boolean prefIndentBracesForMethods;
		final boolean prefIndentBracesForTypes;
		final int prefContinuationIndent;
		final boolean prefHasGenerics;
		final String prefTabChar;

		private final IJavaProject fProject;

		/**
		 * Returns <code>true</code> if the class is used outside the workbench,
		 * <code>false</code> in normal mode
		 *
		 * @return <code>true</code> if the plug-ins are not available
		 */
		private boolean isStandalone() {
			return JavaCore.getPlugin() == null;
		}

		/**
		 * Returns the possibly project-specific core preference defined under <code>key</code>.
		 *
		 * @param key the key of the preference
		 * @return the value of the preference
		 * @since 3.1
		 */
		private String getCoreFormatterOption(String key) {
			if (fProject == null)
				return JavaCore.getOption(key);
			return fProject.getOption(key, true);
		}

		CorePrefs(IJavaProject project) {
			fProject= project;
			if (isStandalone()) {
				prefUseTabs= true;
				prefTabSize= 4;
				prefIndentationSize= 4;
				prefArrayDimensionsDeepIndent= true;
				prefContinuationIndent= 2;
				prefBlockIndent= 1;
				prefArrayIndent= prefContinuationIndent;
				prefArrayDeepIndent= true;
				prefTernaryDeepAlign= false;
				prefTernaryIndent= prefContinuationIndent;
				prefCaseIndent= 0;
				prefCaseBlockIndent= prefBlockIndent;
				prefIndentBracesForBlocks= false;
				prefSimpleIndent= (prefIndentBracesForBlocks && prefBlockIndent == 0) ? 1 : prefBlockIndent;
				prefBracketIndent= prefBlockIndent;
				prefMethodDeclDeepIndent= true;
				prefMethodDeclIndent= 1;
				prefMethodCallDeepIndent= false;
				prefMethodCallIndent= 1;
				prefParenthesisDeepIndent= false;
				prefParenthesisIndent= prefContinuationIndent;
				prefMethodBodyIndent= 1;
				prefTypeIndent= 1;
				prefIndentBracesForArrays= false;
				prefIndentBracesForMethods= false;
				prefIndentBracesForTypes= false;
				prefHasGenerics= false;
				prefTabChar= JavaCore.TAB;
			} else {
				prefUseTabs= prefUseTabs();
				prefTabSize= prefTabSize();
				prefIndentationSize= prefIndentationSize();
				prefArrayDimensionsDeepIndent= prefArrayDimensionsDeepIndent();
				prefContinuationIndent= prefContinuationIndent();
				prefBlockIndent= prefBlockIndent();
				prefArrayIndent= prefArrayIndent();
				prefArrayDeepIndent= prefArrayDeepIndent();
				prefTernaryDeepAlign= prefTernaryDeepAlign();
				prefTernaryIndent= prefTernaryIndent();
				prefCaseIndent= prefCaseIndent();
				prefCaseBlockIndent= prefCaseBlockIndent();
				prefIndentBracesForBlocks= prefIndentBracesForBlocks();
				prefSimpleIndent= prefSimpleIndent();
				prefBracketIndent= prefBracketIndent();
				prefMethodDeclDeepIndent= prefMethodDeclDeepIndent();
				prefMethodDeclIndent= prefMethodDeclIndent();
				prefMethodCallDeepIndent= prefMethodCallDeepIndent();
				prefMethodCallIndent= prefMethodCallIndent();
				prefParenthesisDeepIndent= prefParenthesisDeepIndent();
				prefParenthesisIndent= prefParenthesisIndent();
				prefMethodBodyIndent= prefMethodBodyIndent();
				prefTypeIndent= prefTypeIndent();
				prefIndentBracesForArrays= prefIndentBracesForArrays();
				prefIndentBracesForMethods= prefIndentBracesForMethods();
				prefIndentBracesForTypes= prefIndentBracesForTypes();
				prefHasGenerics= hasGenerics();
				prefTabChar= getCoreFormatterOption(DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR);
			}
		}

		private boolean prefUseTabs() {
			return !JavaCore.SPACE.equals(getCoreFormatterOption(DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR));
		}

		private int prefTabSize() {
			return CodeFormatterUtil.getTabWidth(fProject);
		}

		private int prefIndentationSize() {
			return CodeFormatterUtil.getIndentWidth(fProject);
		}

		private boolean prefArrayDimensionsDeepIndent() {
			return true; // sensible default, no formatter setting
		}

		private int prefArrayIndent() {
			String option= getCoreFormatterOption(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_EXPRESSIONS_IN_ARRAY_INITIALIZER);
			try {
				if (DefaultCodeFormatterConstants.getIndentStyle(option) == DefaultCodeFormatterConstants.INDENT_BY_ONE)
					return 1;
			} catch (IllegalArgumentException e) {
				// ignore and return default
			}

			return prefContinuationIndent(); // default
		}

		private boolean prefArrayDeepIndent() {
			String option= getCoreFormatterOption(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_EXPRESSIONS_IN_ARRAY_INITIALIZER);
			try {
				return DefaultCodeFormatterConstants.getIndentStyle(option) == DefaultCodeFormatterConstants.INDENT_ON_COLUMN;
			} catch (IllegalArgumentException e) {
				// ignore and return default
			}

			return true;
		}

		private boolean prefTernaryDeepAlign() {
			String option= getCoreFormatterOption(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_CONDITIONAL_EXPRESSION);
			try {
				return DefaultCodeFormatterConstants.getIndentStyle(option) == DefaultCodeFormatterConstants.INDENT_ON_COLUMN;
			} catch (IllegalArgumentException e) {
				// ignore and return default
			}
			return false;
		}

		private int prefTernaryIndent() {
			String option= getCoreFormatterOption(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_CONDITIONAL_EXPRESSION);
			try {
				if (DefaultCodeFormatterConstants.getIndentStyle(option) == DefaultCodeFormatterConstants.INDENT_BY_ONE)
					return 1;
				else
					return prefContinuationIndent();
			} catch (IllegalArgumentException e) {
				// ignore and return default
			}

			return prefContinuationIndent();
		}

		private int prefCaseIndent() {
			if (DefaultCodeFormatterConstants.TRUE.equals(getCoreFormatterOption(DefaultCodeFormatterConstants.FORMATTER_INDENT_SWITCHSTATEMENTS_COMPARE_TO_SWITCH)))
				return prefBlockIndent();
			else
				return 0;
		}

		private int prefCaseBlockIndent() {
			if (DefaultCodeFormatterConstants.TRUE.equals(getCoreFormatterOption(DefaultCodeFormatterConstants.FORMATTER_INDENT_SWITCHSTATEMENTS_COMPARE_TO_CASES)))
				return prefBlockIndent();
			else
				return 0;
		}

		private int prefSimpleIndent() {
			if (prefIndentBracesForBlocks() && prefBlockIndent() == 0)
				return 1;
			else return prefBlockIndent();
		}

		private int prefBracketIndent() {
			return prefBlockIndent();
		}

		private boolean prefMethodDeclDeepIndent() {
			String option= getCoreFormatterOption(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_PARAMETERS_IN_METHOD_DECLARATION);
			try {
				return DefaultCodeFormatterConstants.getIndentStyle(option) == DefaultCodeFormatterConstants.INDENT_ON_COLUMN;
			} catch (IllegalArgumentException e) {
				// ignore and return default
			}

			return true;
		}

		private int prefMethodDeclIndent() {
			String option= getCoreFormatterOption(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_PARAMETERS_IN_METHOD_DECLARATION);
			try {
				if (DefaultCodeFormatterConstants.getIndentStyle(option) == DefaultCodeFormatterConstants.INDENT_BY_ONE)
					return 1;
				else
					return prefContinuationIndent();
			} catch (IllegalArgumentException e) {
				// ignore and return default
			}
			return 1;
		}

		private boolean prefMethodCallDeepIndent() {
			String option= getCoreFormatterOption(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_ARGUMENTS_IN_METHOD_INVOCATION);
			try {
				return DefaultCodeFormatterConstants.getIndentStyle(option) == DefaultCodeFormatterConstants.INDENT_ON_COLUMN;
			} catch (IllegalArgumentException e) {
				// ignore and return default
			}
			return false; // sensible default
		}

		private int prefMethodCallIndent() {
			String option= getCoreFormatterOption(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_ARGUMENTS_IN_METHOD_INVOCATION);
			try {
				if (DefaultCodeFormatterConstants.getIndentStyle(option) == DefaultCodeFormatterConstants.INDENT_BY_ONE)
					return 1;
				else
					return prefContinuationIndent();
			} catch (IllegalArgumentException e) {
				// ignore and return default
			}

			return 1; // sensible default
		}

		private boolean prefParenthesisDeepIndent() {
			return false; // don't do parenthesis deep indentation (check rev. 1.60 for experimental code)
		}

		private int prefParenthesisIndent() {
			return prefContinuationIndent();
		}

		private int prefBlockIndent() {
			String option= getCoreFormatterOption(DefaultCodeFormatterConstants.FORMATTER_INDENT_STATEMENTS_COMPARE_TO_BLOCK);
			if (DefaultCodeFormatterConstants.FALSE.equals(option))
				return 0;

			return 1; // sensible default
		}

		private int prefMethodBodyIndent() {
			if (DefaultCodeFormatterConstants.FALSE.equals(getCoreFormatterOption(DefaultCodeFormatterConstants.FORMATTER_INDENT_STATEMENTS_COMPARE_TO_BODY)))
				return 0;

			return 1; // sensible default
		}

		private int prefTypeIndent() {
			String option= getCoreFormatterOption(DefaultCodeFormatterConstants.FORMATTER_INDENT_BODY_DECLARATIONS_COMPARE_TO_TYPE_HEADER);
			if (DefaultCodeFormatterConstants.FALSE.equals(option))
				return 0;

			return 1; // sensible default
		}

		private boolean prefIndentBracesForBlocks() {
			return DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED.equals(getCoreFormatterOption(DefaultCodeFormatterConstants.FORMATTER_BRACE_POSITION_FOR_BLOCK));
		}

		private boolean prefIndentBracesForArrays() {
			return DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED.equals(getCoreFormatterOption(DefaultCodeFormatterConstants.FORMATTER_BRACE_POSITION_FOR_ARRAY_INITIALIZER));
		}

		private boolean prefIndentBracesForMethods() {
			return DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED.equals(getCoreFormatterOption(DefaultCodeFormatterConstants.FORMATTER_BRACE_POSITION_FOR_METHOD_DECLARATION));
		}

		private boolean prefIndentBracesForTypes() {
			return DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED.equals(getCoreFormatterOption(DefaultCodeFormatterConstants.FORMATTER_BRACE_POSITION_FOR_TYPE_DECLARATION));
		}

		private int prefContinuationIndent() {
			try {
				return Integer.parseInt(getCoreFormatterOption(DefaultCodeFormatterConstants.FORMATTER_CONTINUATION_INDENTATION));
			} catch (NumberFormatException e) {
				// ignore and return default
			}

			return 2; // sensible default
		}
		private boolean hasGenerics() {
			return JavaCore.VERSION_1_5.compareTo(getCoreFormatterOption(JavaCore.COMPILER_SOURCE)) <= 0;
		}
	}

	/** The document being scanned. */
	private final IDocument fDocument;
	/** The indentation accumulated by <code>findReferencePosition</code>. */
	private int fIndent;
	/**
	 * The absolute (character-counted) indentation offset for special cases
	 * (method defs, array initializers)
	 */
	private int fAlign;
	/** The stateful scanposition for the indentation methods. */
	private int fPosition;
	/** The previous position. */
	private int fPreviousPos;
	/** The most recent token. */
	private int fToken;
	/** The line of <code>fPosition</code>. */
	private int fLine;
	/**
	 * The scanner we will use to scan the document. It has to be installed
	 * on the same document as the one we get.
	 */
	private final JavaHeuristicScanner fScanner;
	/**
	 * The JDT Core preferences.
	 * @since 3.2
	 */
	private final CorePrefs fPrefs;

	/**
	 * Creates a new instance.
	 *
	 * @param document the document to scan
	 * @param scanner the {@link JavaHeuristicScanner} to be used for scanning
	 * the document. It must be installed on the same <code>IDocument</code>.
	 */
	public JavaIndenter(IDocument document, JavaHeuristicScanner scanner) {
		this(document, scanner, null);
	}

	/**
	 * Creates a new instance.
	 *
	 * @param document the document to scan
	 * @param scanner the {@link JavaHeuristicScanner}to be used for scanning
	 *        the document. It must be installed on the same
	 *        <code>IDocument</code>.
	 * @param project the java project to get the formatter preferences from, or
	 *        <code>null</code> to use the workspace settings
	 * @since 3.1
	 */
	public JavaIndenter(IDocument document, JavaHeuristicScanner scanner, IJavaProject project) {
		Assert.isNotNull(document);
		Assert.isNotNull(scanner);
		fDocument= document;
		fScanner= scanner;
		fPrefs= new CorePrefs(project);
	}

	/**
	 * Computes the indentation at the reference point of <code>position</code>.
	 *
	 * @param offset the offset in the document
	 * @return a String which reflects the indentation at the line in which the
	 *         reference position to <code>offset</code> resides, or <code>null</code>
	 *         if it cannot be determined
	 */
	public StringBuffer getReferenceIndentation(int offset) {
		return getReferenceIndentation(offset, false);
	}

	/**
	 * Computes the indentation at the reference point of <code>position</code>.
	 *
	 * @param offset the offset in the document
	 * @param assumeOpeningBrace <code>true</code> if an opening brace should be assumed
	 * @return a String which reflects the indentation at the line in which the
	 *         reference position to <code>offset</code> resides, or <code>null</code>
	 *         if it cannot be determined
	 */
	private StringBuffer getReferenceIndentation(int offset, boolean assumeOpeningBrace) {

		int unit;
		if (assumeOpeningBrace)
			unit= findReferencePosition(offset, Symbols.TokenLBRACE);
		else
			unit= findReferencePosition(offset, peekChar(offset));

		// if we were unable to find anything, return null
		if (unit == JavaHeuristicScanner.NOT_FOUND)
			return null;

		return getLeadingWhitespace(unit);

	}

	/**
	 * Computes the indentation at <code>offset</code>.
	 *
	 * @param offset the offset in the document
	 * @return a String which reflects the correct indentation for the line in
	 *         which offset resides, or <code>null</code> if it cannot be
	 *         determined
	 */
	public StringBuffer computeIndentation(int offset) {
		return computeIndentation(offset, false);
	}

	/**
	 * Computes the indentation at <code>offset</code>.
	 *
	 * @param offset the offset in the document
	 * @param assumeOpeningBrace <code>true</code> if an opening brace should be assumed
	 * @return a String which reflects the correct indentation for the line in
	 *         which offset resides, or <code>null</code> if it cannot be
	 *         determined
	 */
	public StringBuffer computeIndentation(int offset, boolean assumeOpeningBrace) {

		StringBuffer reference= getReferenceIndentation(offset, assumeOpeningBrace);

		// handle special alignment
		if (fAlign != JavaHeuristicScanner.NOT_FOUND) {
			try {
				// a special case has been detected.
				IRegion line= fDocument.getLineInformationOfOffset(fAlign);
				int lineOffset= line.getOffset();
				return createIndent(lineOffset, fAlign, false);
			} catch (BadLocationException e) {
				return null;
			}
		}

		if (reference == null)
			return null;

		// add additional indent
		return createReusingIndent(reference, fIndent);
	}

	/**
	 * Computes the length of a <code>CharacterSequence</code>, counting
	 * a tab character as the size until the next tab stop and every other
	 * character as one.
	 *
	 * @param indent the string to measure
	 * @return the visual length in characters
	 */
	private int computeVisualLength(CharSequence indent) {
		final int tabSize= fPrefs.prefTabSize;
		int length= 0;
		for (int i= 0; i < indent.length(); i++) {
			char ch= indent.charAt(i);
			switch (ch) {
				case '\t':
					if (tabSize > 0) {
						int reminder= length % tabSize;
						length += tabSize - reminder;
					}
					break;
				case ' ':
					length++;
					break;
			}
		}
		return length;
	}

	/**
	 * Strips any characters off the end of <code>reference</code> that exceed
	 * <code>indentLength</code>.
	 *
	 * @param reference the string to measure
	 * @param indentLength the maximum visual indentation length
	 * @return the stripped <code>reference</code>
	 */
	private StringBuffer stripExceedingChars(StringBuffer reference, int indentLength) {
		final int tabSize= fPrefs.prefTabSize;
		int measured= 0;
		int chars= reference.length();
		int i= 0;
		for (; measured < indentLength && i < chars; i++) {
			char ch= reference.charAt(i);
			switch (ch) {
				case '\t':
					if (tabSize > 0) {
						int reminder= measured % tabSize;
						measured += tabSize - reminder;
					}
					break;
				case ' ':
					measured++;
					break;
			}
		}
		int deleteFrom= measured > indentLength ? i - 1 : i;

		return reference.delete(deleteFrom, chars);
	}

	/**
	 * Returns the indentation of the line at <code>offset</code> as a
	 * <code>StringBuffer</code>. If the offset is not valid, the empty string
	 * is returned.
	 *
	 * @param offset the offset in the document
	 * @return the indentation (leading whitespace) of the line in which
	 * 		   <code>offset</code> is located
	 */
	private StringBuffer getLeadingWhitespace(int offset) {
		StringBuffer indent= new StringBuffer();
		try {
			IRegion line= fDocument.getLineInformationOfOffset(offset);
			int lineOffset= line.getOffset();
			int nonWS= fScanner.findNonWhitespaceForwardInAnyPartition(lineOffset, lineOffset + line.getLength());
			indent.append(fDocument.get(lineOffset, nonWS - lineOffset));
			return indent;
		} catch (BadLocationException e) {
			return indent;
		}
	}

	/**
	 * Creates an indentation string of the length indent - start, consisting of
	 * the content in <code>fDocument</code> in the range [start, indent),
	 * with every character replaced by a space except for tabs, which are kept
	 * as such.
	 * <p>
	 * If <code>convertSpaceRunsToTabs</code> is <code>true</code>, every
	 * run of the number of spaces that make up a tab are replaced by a tab
	 * character. If it is not set, no conversion takes place, but tabs in the
	 * original range are still copied verbatim.
	 * </p>
	 *
	 * @param start the start of the document region to copy the indent from
	 * @param indent the exclusive end of the document region to copy the indent
	 *        from
	 * @param convertSpaceRunsToTabs whether to convert consecutive runs of
	 *        spaces to tabs
	 * @return the indentation corresponding to the document content specified
	 *         by <code>start</code> and <code>indent</code>
	 */
	private StringBuffer createIndent(int start, final int indent, final boolean convertSpaceRunsToTabs) {
		final boolean convertTabs= fPrefs.prefUseTabs && convertSpaceRunsToTabs;
		final int tabLen= fPrefs.prefTabSize;
		final StringBuffer ret= new StringBuffer();
		try {
			int spaces= 0;
			while (start < indent) {

				char ch= fDocument.getChar(start);
				if (ch == '\t') {
					ret.append('\t');
					spaces= 0;
				} else if (convertTabs) {
					spaces++;
					if (spaces == tabLen) {
						ret.append('\t');
						spaces= 0;
					}
				} else {
					ret.append(' ');
				}

				start++;
			}
			// remainder
			while (spaces-- > 0)
				ret.append(' ');

		} catch (BadLocationException e) {
		}

		return ret;
	}

	/**
	 * Creates a string with a visual length of the given
	 * <code>indentationSize</code>.
	 *
	 * @param buffer the original indent to reuse if possible
	 * @param additional the additional indentation units to add or subtract to
	 *        reference
	 * @return the modified <code>buffer</code> reflecting the indentation
	 *         adapted to <code>additional</code>
	 */
	private StringBuffer createReusingIndent(StringBuffer buffer, int additional) {
		int refLength= computeVisualLength(buffer);
		int addLength= fPrefs.prefIndentationSize * additional; // may be < 0
		int totalLength= Math.max(0, refLength + addLength);


		// copy the reference indentation for the indent up to the last tab
		// stop within the maxCopy area
		int minLength= Math.min(totalLength, refLength);
		int tabSize= fPrefs.prefTabSize;
		int maxCopyLength= tabSize > 0 ? minLength - minLength % tabSize : minLength; // maximum indent to copy
		stripExceedingChars(buffer, maxCopyLength);


		// add additional indent
		int missing= totalLength - maxCopyLength;
		final int tabs, spaces;
		if (JavaCore.SPACE.equals(fPrefs.prefTabChar)) {
			tabs= 0;
			spaces= missing;
		} else if (JavaCore.TAB.equals(fPrefs.prefTabChar)) {
			tabs= tabSize > 0 ? missing / tabSize : 0;
			spaces= tabSize > 0 ? missing % tabSize : missing;
		} else if (DefaultCodeFormatterConstants.MIXED.equals(fPrefs.prefTabChar)) {
			tabs= tabSize > 0 ? missing / tabSize : 0;
			spaces= tabSize > 0 ? missing % tabSize : missing;
		} else {
			Assert.isTrue(false);
			return null;
		}
		for(int i= 0; i < tabs; i++)
			buffer.append('\t');
		for(int i= 0; i < spaces; i++)
			buffer.append(' ');
		return buffer;
	}

	/**
	 * Returns the reference position regarding to indentation for <code>offset</code>,
	 * or <code>NOT_FOUND</code>. This method calls
	 * {@link #findReferencePosition(int, int) findReferencePosition(offset, nextChar)} where
	 * <code>nextChar</code> is the next character after <code>offset</code>.
	 *
	 * @param offset the offset for which the reference is computed
	 * @return the reference statement relative to which <code>offset</code>
	 *         should be indented, or {@link JavaHeuristicScanner#NOT_FOUND}
	 */
	public int findReferencePosition(int offset) {
		return findReferencePosition(offset, peekChar(offset));
	}

	/**
	 * Peeks the next char in the document that comes after <code>offset</code>
	 * on the same line as <code>offset</code>.
	 *
	 * @param offset the offset into document
	 * @return the token symbol of the next element, or TokenEOF if there is none
	 */
	private int peekChar(int offset) {
		if (offset < fDocument.getLength()) {
			try {
				IRegion line= fDocument.getLineInformationOfOffset(offset);
				int lineOffset= line.getOffset();
				int next= fScanner.nextToken(offset, lineOffset + line.getLength());
				return next;
			} catch (BadLocationException e) {
			}
		}
		return Symbols.TokenEOF;
	}

	/**
	 * Returns the reference position regarding to indentation for <code>position</code>,
	 * or <code>NOT_FOUND</code>.
	 *
	 * <p>If <code>peekNextChar</code> is <code>true</code>, the next token after
	 * <code>offset</code> is read and taken into account when computing the
	 * indentation. Currently, if the next token is the first token on the line
	 * (i.e. only preceded by whitespace), the following tokens are specially
	 * handled:
	 * <ul>
	 * 	<li><code>switch</code> labels are indented relative to the switch block</li>
	 * 	<li>opening curly braces are aligned correctly with the introducing code</li>
	 * 	<li>closing curly braces are aligned properly with the introducing code of
	 * 		the matching opening brace</li>
	 * 	<li>closing parenthesis' are aligned with their opening peer</li>
	 * 	<li>the <code>else</code> keyword is aligned with its <code>if</code>, anything
	 * 		else is aligned normally (i.e. with the base of any introducing statements).</li>
	 *  <li>if there is no token on the same line after <code>offset</code>, the indentation
	 * 		is the same as for an <code>else</code> keyword</li>
	 * </ul>
	 *
	 * @param offset the offset for which the reference is computed
	 * @param nextToken the next token to assume in the document
	 * @return the reference statement relative to which <code>offset</code>
	 *         should be indented, or {@link JavaHeuristicScanner#NOT_FOUND}
	 */
	public int findReferencePosition(int offset, int nextToken) {
		boolean danglingElse= false;
		boolean unindent= false;
		boolean indent= false;
		boolean matchBrace= false;
		boolean matchParen= false;
		boolean matchCase= false;
		boolean throwsClause= false;

		// account for un-indentation characters already typed in, but after position
		// if they are on a line by themselves, the indentation gets adjusted
		// accordingly
		//
		// also account for a dangling else
		if (offset < fDocument.getLength()) {
			try {
				IRegion line= fDocument.getLineInformationOfOffset(offset);
				int lineOffset= line.getOffset();
				int prevPos= Math.max(offset - 1, 0);
				boolean isFirstTokenOnLine= fDocument.get(lineOffset, prevPos + 1 - lineOffset).trim().length() == 0;
				int prevToken= fScanner.previousToken(prevPos, JavaHeuristicScanner.UNBOUND);
				boolean bracelessBlockStart= fScanner.isBracelessBlockStart(prevPos, JavaHeuristicScanner.UNBOUND);

				switch (nextToken) {
					case Symbols.TokenELSE:
						danglingElse= true;
						break;
					case Symbols.TokenCASE:
					case Symbols.TokenDEFAULT:
						if (isFirstTokenOnLine)
							matchCase= true;
						break;
					case Symbols.TokenLBRACE: // for opening-brace-on-new-line style
						if (bracelessBlockStart && !fPrefs.prefIndentBracesForBlocks)
							unindent= true;
						else if ((prevToken == Symbols.TokenCOLON || prevToken == Symbols.TokenEQUAL) && !fPrefs.prefIndentBracesForArrays)
							unindent= true;
						else if (!bracelessBlockStart && fPrefs.prefIndentBracesForMethods)
							indent= true;
						break;
					case Symbols.TokenRBRACE: // closing braces get unindented
						if (isFirstTokenOnLine)
							matchBrace= true;
						break;
					case Symbols.TokenRPAREN:
						if (isFirstTokenOnLine)
							matchParen= true;
						break;
					case Symbols.TokenTHROWS:
						throwsClause= true;
						break;
					case Symbols.TokenPLUS:
						if (isStringContinuation(offset)) {
							if (isSecondLineOfStringContinuation(offset)) {
								fAlign= JavaHeuristicScanner.NOT_FOUND;
								fIndent= fPrefs.prefContinuationIndent;
							} else {
								int previousLineOffset= fDocument.getLineOffset(fDocument.getLineOfOffset(offset) - 1);
								fAlign= fScanner.findNonWhitespaceForwardInAnyPartition(previousLineOffset, JavaHeuristicScanner.UNBOUND);
							}
							return fPosition;
						}
						break;
				}
			} catch (BadLocationException e) {
			}
		} else {
			// don't assume an else could come if we are at the end of file
			danglingElse= false;
		}

		int ref= findReferencePosition(offset, danglingElse, matchBrace, matchParen, matchCase, throwsClause);
		if (unindent)
			fIndent--;
		if (indent)
			fIndent++;
		return ref;
	}

	/**
	 * Tells whether the given string is a continuation expression.
	 * 
	 * @param offset the offset for which the check is done
	 * @return <code>true</code> if the offset is part of a string continuation, <code>false</code>
	 *         otherwise
	 * @since 3.7
	 */
	private boolean isStringContinuation(int offset) {
		int nextNonWSCharPosition= fScanner.findNonWhitespaceBackwardInAnyPartition(offset - 1, JavaHeuristicScanner.UNBOUND);
		try {
			if (fDocument.getChar(nextNonWSCharPosition) == '"')
				return true;
			else
				return false;
		} catch (BadLocationException e) {
			JavaPlugin.log(e);
			return false;
		}
	}

	/**
	 * Checks if extra indentation for second line of string continuation is required.
	 * 
	 * @param offset the offset for which the check is done
	 * @return returns <code>true</code> if extra indentation for second line of string continuation
	 *         is required
	 * @since 3.7
	 */
	private boolean isSecondLineOfStringContinuation(int offset) {
		try {
			int offsetLine= fDocument.getLineOfOffset(offset);
			fPosition= offset;
			while (true) {
				nextToken();
				switch (fToken) {
				// scopes: skip them
					case Symbols.TokenRPAREN:
					case Symbols.TokenRBRACKET:
					case Symbols.TokenRBRACE:
					case Symbols.TokenGREATERTHAN:
						skipScope();
						break;

					case Symbols.TokenPLUS:
						if ((offsetLine - fLine) > 1) {
							return false;
						}
						break;

					case Symbols.TokenCOMMA:
					case Symbols.TokenLPAREN:
					case Symbols.TokenLBRACE:
					case Symbols.TokenEQUAL:
						int stringStartingOffset= fScanner.findNonWhitespaceForwardInAnyPartition(fPosition + 1, JavaHeuristicScanner.UNBOUND);
						int stringStartingLine= fDocument.getLineOfOffset(stringStartingOffset);
						if ((offsetLine - stringStartingLine) == 1) {
							fPosition= stringStartingOffset;
							return true;
						} else {
							return false;
						}
					case Symbols.TokenLBRACKET:
					case Symbols.TokenEOF:
						if ((offsetLine - fLine) == 1)
							return true;
						else
							return false;
				}
			}
		} catch (BadLocationException e) {
			JavaPlugin.log(e);
			return false;
		}
	}

	/**
	 * Returns the reference position regarding to indentation for <code>position</code>, or
	 * <code>NOT_FOUND</code>.<code>fIndent</code> will contain the relative indentation (in
	 * indentation units, not characters) after the call. If there is a special alignment (e.g. for
	 * a method declaration where parameters should be aligned), <code>fAlign</code> will contain
	 * the absolute position of the alignment reference in <code>fDocument</code>, otherwise
	 * <code>fAlign</code> is set to <code>JavaHeuristicScanner.NOT_FOUND</code>. This method calls
	 * {@link #findReferencePosition(int, boolean, boolean, boolean, boolean, boolean)
	 * findReferencePosition(offset, danglingElse, matchBrace, matchParen, matchCase, throwsClause)}
	 * where <code>throwsClause</code> indicates whether a throws clause was found at
	 * <code>position</code>.
	 * 
	 * @param offset the offset for which the reference is computed
	 * @param danglingElse whether a dangling else should be assumed at <code>position</code>
	 * @param matchBrace whether the position of the matching brace should be returned instead of
	 *            doing code analysis
	 * @param matchParen whether the position of the matching parenthesis should be returned instead
	 *            of doing code analysis
	 * @param matchCase whether the position of a switch statement reference should be returned
	 *            (either an earlier case statement or the switch block brace)
	 * @return the reference statement relative to which <code>position</code> should be indented,
	 *         or {@link JavaHeuristicScanner#NOT_FOUND}
	 */
	public int findReferencePosition(int offset, boolean danglingElse, boolean matchBrace, boolean matchParen, boolean matchCase) {
		return findReferencePosition(offset, danglingElse, matchBrace, matchParen, matchCase, false);
	}

	/**
	 * Returns the reference position regarding to indentation for <code>position</code>, or
	 * <code>NOT_FOUND</code>.<code>fIndent</code> will contain the relative indentation (in
	 * indentation units, not characters) after the call. If there is a special alignment (e.g. for
	 * a method declaration where parameters should be aligned), <code>fAlign</code> will contain
	 * the absolute position of the alignment reference in <code>fDocument</code>, otherwise
	 * <code>fAlign</code> is set to <code>JavaHeuristicScanner.NOT_FOUND</code>.
	 * 
	 * @param offset the offset for which the reference is computed
	 * @param danglingElse whether a dangling else should be assumed at <code>position</code>
	 * @param matchBrace whether the position of the matching brace should be returned instead of
	 *            doing code analysis
	 * @param matchParen whether the position of the matching parenthesis should be returned instead
	 *            of doing code analysis
	 * @param matchCase whether the position of a switch statement reference should be returned
	 *            (either an earlier case statement or the switch block brace)
	 * @param throwsClause whether a throws clause was found at <code>position</code>
	 * @return the reference statement relative to which <code>position</code> should be indented,
	 *         or {@link JavaHeuristicScanner#NOT_FOUND}
	 * @since 3.7
	 */
	public int findReferencePosition(int offset, boolean danglingElse, boolean matchBrace, boolean matchParen, boolean matchCase, boolean throwsClause) {
		fIndent= 0; // the indentation modification
		fAlign= JavaHeuristicScanner.NOT_FOUND;
		fPosition= offset;

		// forward cases
		// an unindentation happens sometimes if the next token is special, namely on braces, parens and case labels
		// align braces, but handle the case where we align with the method declaration start instead of
		// the opening brace.
		if (matchBrace) {
			if (skipScope(Symbols.TokenLBRACE, Symbols.TokenRBRACE)) {
				try {
					// align with the opening brace that is on a line by its own
					int lineOffset= fDocument.getLineOffset(fLine);
					if (lineOffset <= fPosition && fDocument.get(lineOffset, fPosition - lineOffset).trim().length() == 0)
						return fPosition;
				} catch (BadLocationException e) {
					// concurrent modification - walk default path
				}
				// if the opening brace is not on the start of the line, skip to the start
				int pos= skipToStatementStart(true, true);
				fIndent= 0; // indent is aligned with reference position
				return pos;
			} else {
				// if we can't find the matching brace, the heuristic is to unindent
				// by one against the normal position
				int pos= findReferencePosition(offset, danglingElse, false, matchParen, matchCase, throwsClause);
				fIndent--;
				return pos;
			}
		}

		// align parenthesis'
		if (matchParen) {
			if (skipScope(Symbols.TokenLPAREN, Symbols.TokenRPAREN)) {
				fIndent= fPrefs.prefContinuationIndent;
				return fPosition;
			} else {
				// if we can't find the matching paren, the heuristic is to unindent
				// by one against the normal position
				int pos= findReferencePosition(offset, danglingElse, matchBrace, false, matchCase, throwsClause);
				fIndent--;
				return pos;
			}
		}

		// the only reliable way to get case labels aligned (due to many different styles of using braces in a block)
		// is to go for another case statement, or the scope opening brace
		if (matchCase) {
			return matchCaseAlignment();
		}

		nextToken();
		switch (fToken) {
			case Symbols.TokenGREATERTHAN:
			case Symbols.TokenRBRACE:
				// skip the block and fall through
				// if we can't complete the scope, reset the scan position
				int pos= fPosition;
				if (!skipScope())
					fPosition= pos;
				return skipToStatementStart(danglingElse, false);
			case Symbols.TokenSEMICOLON:
				// this is the 90% case: after a statement block
				// the end of the previous statement / block previous.end
				// search to the end of the statement / block before the previous; the token just after that is previous.start
				pos= fPosition;
				if (isSemicolonPartOfForStatement()) {
					fIndent= fPrefs.prefContinuationIndent;
					return fPosition;
				} else {
					fPosition= pos;
					if (isTryWithResources()) {
						fIndent= fPrefs.prefContinuationIndent;
						return fPosition;
					} else {
						fPosition= pos;
						return skipToStatementStart(danglingElse, false);
					}
				}
			// scope introduction: special treat who special is
			case Symbols.TokenLPAREN:
			case Symbols.TokenLBRACE:
			case Symbols.TokenLBRACKET:
				return handleScopeIntroduction(offset + 1);

			case Symbols.TokenEOF:
				// trap when hitting start of document
				return JavaHeuristicScanner.NOT_FOUND;

			case Symbols.TokenEQUAL:
				// indent assignments
				return handleEqual();

			case Symbols.TokenCOLON:
				// TODO handle ternary deep indentation
				fIndent= fPrefs.prefCaseBlockIndent;
				return fPosition;

			case Symbols.TokenQUESTIONMARK:
				if (fPrefs.prefTernaryDeepAlign) {
					setFirstElementAlignment(fPosition, offset + 1);
					return fPosition;
				} else {
					fIndent= fPrefs.prefTernaryIndent;
					return fPosition;
				}

			// indentation for blockless introducers:
			case Symbols.TokenDO:
			case Symbols.TokenWHILE:
			case Symbols.TokenELSE:
				fIndent= fPrefs.prefSimpleIndent;
				return fPosition;

			case Symbols.TokenTRY:
				return skipToStatementStart(danglingElse, false);

			case Symbols.TokenRBRACKET:
				fIndent= fPrefs.prefContinuationIndent;
				return fPosition;

			case Symbols.TokenRPAREN:
				if (throwsClause) {
					fIndent= fPrefs.prefContinuationIndent;
					return fPosition;
				}
				int line= fLine;
				if (skipScope(Symbols.TokenLPAREN, Symbols.TokenRPAREN)) {
					int scope= fPosition;
					nextToken();
					if (fToken == Symbols.TokenIF || fToken == Symbols.TokenWHILE || fToken == Symbols.TokenFOR) {
						fIndent= fPrefs.prefSimpleIndent;
						return fPosition;
					}
					fPosition= scope;
					if (looksLikeMethodDecl()) {
						return skipToStatementStart(danglingElse, false);
					}
					if (fToken == Symbols.TokenCATCH) {
						return skipToStatementStart(danglingElse, false);
					}
					fPosition= scope;
					if (looksLikeAnonymousTypeDecl()) {
						return skipToStatementStart(danglingElse, false);
					}
					fPosition= scope;
					if (looksLikeAnnotation()) {
						return skipToStatementStart(danglingElse, false);
					}
				}
				// restore
				fPosition= offset;
				fLine= line;

				return skipToPreviousListItemOrListStart();
			case Symbols.TokenRETURN:
				fIndent= fPrefs.prefContinuationIndent;
				return fPosition;
			case Symbols.TokenPLUS:
				if (isStringContinuation(fPosition)) {
					try {
						if (isSecondLineOfStringContinuation(offset)) {
							fAlign= JavaHeuristicScanner.NOT_FOUND;
							fIndent= fPrefs.prefContinuationIndent;
						} else {
							int previousLineOffset= fDocument.getLineOffset(fDocument.getLineOfOffset(offset) - 1);
							fAlign= fScanner.findNonWhitespaceForwardInAnyPartition(previousLineOffset, JavaHeuristicScanner.UNBOUND);
						}
					} catch (BadLocationException e) {
						JavaPlugin.log(e);
					}
					return fPosition;
				}
				fPosition= offset;
				return skipToPreviousListItemOrListStart();
			case Symbols.TokenCOMMA:
				// inside a list of some type
				// easy if there is already a list item before with its own indentation - we just align
				// if not: take the start of the list ( LPAREN, LBRACE, LBRACKET ) and either align or
				// indent by list-indent
			default:
				// inside whatever we don't know about: similar to the list case:
				// if we are inside a continued expression, then either align with a previous line that has indentation
				// or indent from the expression start line (either a scope introducer or the start of the expr).
				return skipToPreviousListItemOrListStart();
		}
	}

	/**
	 * Checks if the statement at position is itself a continuation of the previous, else sets the
	 * indentation to Continuation Indent.
	 * 
	 * @return the position of the token
	 * @since 3.7
	 */
	private int handleEqual() {
		try {
			//If this line is itself continuation of the previous then do nothing
			IRegion line= fDocument.getLineInformationOfOffset(fPosition);
			int nonWS= fScanner.findNonWhitespaceBackward(line.getOffset(), JavaHeuristicScanner.UNBOUND);
			if (nonWS != Symbols.TokenEOF) {
				int tokenAtPreviousLine= fScanner.nextToken(nonWS, nonWS + 1);
				if (tokenAtPreviousLine != Symbols.TokenSEMICOLON && tokenAtPreviousLine != Symbols.TokenRBRACE && tokenAtPreviousLine != Symbols.TokenLBRACE
						&& tokenAtPreviousLine != Symbols.TokenEOF)
					return fPosition;
			}
		} catch (BadLocationException e) {
			return fPosition;
		}

		fIndent= fPrefs.prefContinuationIndent;
		return fPosition;
	}

	/**
	 * Checks if the semicolon at the current position is part of a for statement.
	 * 
	 * @return returns <code>true</code> if current position is part of for statement
	 * @since 3.7
	 */
	private boolean isSemicolonPartOfForStatement() {
		int semiColonCount= 1;
		while (true) {
			nextToken();
			switch (fToken) {
				case Symbols.TokenFOR:
					return true;
				case Symbols.TokenLBRACE:
					return false;
				case Symbols.TokenSEMICOLON:
					semiColonCount++;
					if (semiColonCount > 2)
						return false;
					break;
				case Symbols.TokenCOLON:
					return false;
				case Symbols.TokenEOF:
					return false;
			}
		}
	}

	/**
	 * Checks if the semicolon at the current position is part of a try with resources statement.
	 * 
	 * @return returns <code>true</code> if current position is part of try with resources statement
	 * @since 3.7
	 */
	private boolean isTryWithResources() {
		while (true) {
			nextToken();
			switch (fToken) {
				case Symbols.TokenTRY:
					return true;
				case Symbols.TokenLBRACE:
					return false;
				case Symbols.TokenEOF:
					return false;
			}
		}
	}

	/**
	 * Skips to the start of a statement that ends at the current position.
	 *
	 * @param danglingElse whether to indent aligned with the last <code>if</code>
	 * @param isInBlock whether the current position is inside a block, which limits the search scope to the next scope introducer
	 * @return the reference offset of the start of the statement
	 */
	private int skipToStatementStart(boolean danglingElse, boolean isInBlock) {
		final int NOTHING= 0;
		final int READ_PARENS= 1;
		final int READ_IDENT= 2;
		int mayBeMethodBody= NOTHING;
		boolean isTypeBody= false;
		while (true) {
			nextToken();

			if (isInBlock) {
				switch (fToken) {
					// exit on all block introducers
					case Symbols.TokenIF:
					case Symbols.TokenELSE:
					case Symbols.TokenCATCH:
					case Symbols.TokenDO:
					case Symbols.TokenWHILE:
					case Symbols.TokenFINALLY:
					case Symbols.TokenFOR:
					case Symbols.TokenTRY:
						return fPosition;

					case Symbols.TokenSTATIC:
						mayBeMethodBody= READ_IDENT; // treat static blocks like methods
						break;

					case Symbols.TokenSYNCHRONIZED:
						// if inside a method declaration, use body indentation
						// else use block indentation.
						if (mayBeMethodBody != READ_IDENT)
							return fPosition;
						break;

					case Symbols.TokenCLASS:
					case Symbols.TokenINTERFACE:
					case Symbols.TokenENUM:
						isTypeBody= true;
						break;

					case Symbols.TokenSWITCH:
						fIndent= fPrefs.prefCaseIndent;
						return fPosition;
				}
			}

			switch (fToken) {
				// scope introduction through: LPAREN, LBRACE, LBRACKET
				// search stop on SEMICOLON, RBRACE, COLON, EOF
				// -> the next token is the start of the statement (i.e. previousPos when backward scanning)
				case Symbols.TokenLPAREN:
				case Symbols.TokenLBRACE:
				case Symbols.TokenLBRACKET:
				case Symbols.TokenSEMICOLON:
				case Symbols.TokenEOF:
					if (isInBlock)
						fIndent= getBlockIndent(mayBeMethodBody == READ_IDENT, isTypeBody);
					// else: fIndent set by previous calls
					return fPreviousPos;

				case Symbols.TokenCOLON:
					int pos= fPreviousPos;
					if (!isConditional())
						return pos;
					break;

				case Symbols.TokenRBRACE:
					// RBRACE is a little tricky: it can be the end of an array definition, but
					// usually it is the end of a previous block
					pos= fPreviousPos; // store state
					if (skipScope() && looksLikeArrayInitializerIntro()) {
						continue; // it's an array
					} else {
						if (isInBlock)
							fIndent= getBlockIndent(mayBeMethodBody == READ_IDENT, isTypeBody);
						return pos; // it's not - do as with all the above
					}

				// scopes: skip them
				case Symbols.TokenRPAREN:
					if (isInBlock)
						mayBeMethodBody= READ_PARENS;
					//$FALL-THROUGH$
				case Symbols.TokenRBRACKET:
				case Symbols.TokenGREATERTHAN:
					pos= fPreviousPos;
					if (skipScope())
						break;
					else
						return pos;

				// IF / ELSE: align the position after the conditional block with the if
				// so we are ready for an else, except if danglingElse is false
				// in order for this to work, we must skip an else to its if
				case Symbols.TokenIF:
					if (danglingElse)
						return fPosition;
					else
						break;
				case Symbols.TokenELSE:
					// skip behind the next if, as we have that one covered
					pos= fPosition;
					if (skipNextIF())
						break;
					else
						return pos;

				case Symbols.TokenCATCH:
				case Symbols.TokenFINALLY:
					pos= fPosition;
					if (skipNextTRY())
						break;
					else
						return pos;

				case Symbols.TokenDO:
					// align the WHILE position with its do
					return fPosition;

				case Symbols.TokenWHILE:
					// this one is tricky: while can be the start of a while loop
					// or the end of a do - while
					pos= fPosition;
					if (hasMatchingDo()) {
						// continue searching from the DO on
						break;
					} else {
						// continue searching from the WHILE on
						fPosition= pos;
						break;
					}
				case Symbols.TokenIDENT:
					if (mayBeMethodBody == READ_PARENS)
						mayBeMethodBody= READ_IDENT;
					break;

				default:
					// keep searching

			}

		}
	}

	private int getBlockIndent(boolean isMethodBody, boolean isTypeBody) {
		if (isTypeBody)
			return fPrefs.prefTypeIndent + (fPrefs.prefIndentBracesForTypes ? 1 : 0);
		else if (isMethodBody)
			return fPrefs.prefMethodBodyIndent + (fPrefs.prefIndentBracesForMethods ? 1 : 0);
		else
			return fIndent;
	}

	/**
	 * Returns true if the colon at the current position is part of a conditional
	 * (ternary) expression, false otherwise.
	 *
	 * @return true if the colon at the current position is part of a conditional
	 */
	private boolean isConditional() {
		while (true) {
			nextToken();
			switch (fToken) {

				// search for case labels, which consist of (possibly qualified) identifiers or numbers
				case Symbols.TokenIDENT:
				case Symbols.TokenOTHER: // dots for qualified constants
					continue;
				case Symbols.TokenCASE:
				case Symbols.TokenDEFAULT:
					return false;
				default:
					return true;
			}
		}
	}

	/**
	 * Returns as a reference any previous <code>switch</code> labels (<code>case</code>
	 * or <code>default</code>) or the offset of the brace that scopes the switch
	 * statement. Sets <code>fIndent</code> to <code>prefCaseIndent</code> upon
	 * a match.
	 *
	 * @return the reference offset for a <code>switch</code> label
	 */
	private int matchCaseAlignment() {
		while (true) {
			nextToken();
			switch (fToken) {
				// invalid cases: another case label or an LBRACE must come before a case
				// -> bail out with the current position
				case Symbols.TokenLPAREN:
				case Symbols.TokenLBRACKET:
				case Symbols.TokenEOF:
					return fPosition;
				case Symbols.TokenLBRACE:
					// opening brace of switch statement
					fIndent= fPrefs.prefCaseIndent;
					return fPosition;
				case Symbols.TokenCASE:
				case Symbols.TokenDEFAULT:
					// align with previous label
					fIndent= 0;
					return fPosition;

				// scopes: skip them
				case Symbols.TokenRPAREN:
				case Symbols.TokenRBRACKET:
				case Symbols.TokenRBRACE:
				case Symbols.TokenGREATERTHAN:
					skipScope();
					break;

				default:
					// keep searching
					continue;

			}
		}
	}

	/**
	 * Returns the reference position for a list element. The algorithm
	 * tries to match any previous indentation on the same list. If there is none,
	 * the reference position returned is determined depending on the type of list:
	 * The indentation will either match the list scope introducer (e.g. for
	 * method declarations), so called deep indents, or simply increase the
	 * indentation by a number of standard indents. See also {@link #handleScopeIntroduction(int)}.
	 *
	 * @return the reference position for a list item: either a previous list item
	 * that has its own indentation, or the list introduction start.
	 */
	private int skipToPreviousListItemOrListStart() {
		int startLine= fLine;
		int startPosition= fPosition;
		while (true) {
			nextToken();

			// if any line item comes with its own indentation, adapt to it
			if (fLine < startLine) {
				try {
					int lineOffset= fDocument.getLineOffset(startLine);
					int bound= Math.min(fDocument.getLength(), startPosition + 1);
					fAlign= fScanner.findNonWhitespaceForwardInAnyPartition(lineOffset, bound);
				} catch (BadLocationException e) {
					// ignore and return just the position
				}
				return startPosition;
			}

			switch (fToken) {
				// scopes: skip them
				case Symbols.TokenRPAREN:
				case Symbols.TokenRBRACKET:
				case Symbols.TokenRBRACE:
				case Symbols.TokenGREATERTHAN:
					skipScope();
					break;

				// scope introduction: special treat who special is
				case Symbols.TokenLPAREN:
				case Symbols.TokenLBRACE:
				case Symbols.TokenLBRACKET:
					return handleScopeIntroduction(startPosition + 1);

				case Symbols.TokenSEMICOLON:
					int savedPosition= fPosition;
					if (isSemicolonPartOfForStatement())
						fIndent= fPrefs.prefContinuationIndent;
					else
						fPosition= savedPosition;
					return fPosition;
				case Symbols.TokenQUESTIONMARK:
					if (fPrefs.prefTernaryDeepAlign) {
						setFirstElementAlignment(fPosition - 1, fPosition + 1);
						return fPosition;
					} else {
						fIndent= fPrefs.prefTernaryIndent;
						return fPosition;
					}
				case Symbols.TokenRETURN:
					fIndent= fPrefs.prefContinuationIndent;
					return fPosition;
				case Symbols.TokenEQUAL:
					return handleEqual();
				case Symbols.TokenEOF:
					return 0;

			}
		}
	}

	/**
	 * Skips a scope and positions the cursor (<code>fPosition</code>) on the
	 * token that opens the scope. Returns <code>true</code> if a matching peer
	 * could be found, <code>false</code> otherwise. The current token when calling
	 * must be one out of <code>Symbols.TokenRPAREN</code>, <code>Symbols.TokenRBRACE</code>,
	 * and <code>Symbols.TokenRBRACKET</code>.
	 *
	 * @return <code>true</code> if a matching peer was found, <code>false</code> otherwise
	 */
	private boolean skipScope() {
		switch (fToken) {
			case Symbols.TokenRPAREN:
				return skipScope(Symbols.TokenLPAREN, Symbols.TokenRPAREN);
			case Symbols.TokenRBRACKET:
				return skipScope(Symbols.TokenLBRACKET, Symbols.TokenRBRACKET);
			case Symbols.TokenRBRACE:
				return skipScope(Symbols.TokenLBRACE, Symbols.TokenRBRACE);
			case Symbols.TokenGREATERTHAN:
				if (!fPrefs.prefHasGenerics)
					return false;
				int storedPosition= fPosition;
				int storedToken= fToken;
				nextToken();
				switch (fToken) {
					case Symbols.TokenIDENT:
						boolean isGenericStarter;
						try {
							isGenericStarter= !JavaHeuristicScanner.isGenericStarter(getTokenContent());
						} catch (BadLocationException e) {
							return false;
						}
						if (isGenericStarter)
							break;
						//$FALL-THROUGH$
					case Symbols.TokenQUESTIONMARK:
					case Symbols.TokenGREATERTHAN:
						if (skipScope(Symbols.TokenLESSTHAN, Symbols.TokenGREATERTHAN))
							return true;
				}
				// <> are harder to detect - restore the position if we fail
				fPosition= storedPosition;
				fToken= storedToken;
				return false;

			default:
				Assert.isTrue(false);
				return false;
		}
	}

	/**
	 * Returns the contents of the current token.
	 * 
	 * @return the contents of the current token
	 * @throws BadLocationException if the indices are out of bounds
	 * @since 3.1
	 */
	private CharSequence getTokenContent() throws BadLocationException {
		return new DocumentCharacterIterator(fDocument, fPosition, fPreviousPos);
	}

	/**
	 * Handles the introduction of a new scope. The current token must be one out
	 * of <code>Symbols.TokenLPAREN</code>, <code>Symbols.TokenLBRACE</code>,
	 * and <code>Symbols.TokenLBRACKET</code>. Returns as the reference position
	 * either the token introducing the scope or - if available - the first
	 * java token after that.
	 *
	 * <p>Depending on the type of scope introduction, the indentation will align
	 * (deep indenting) with the reference position (<code>fAlign</code> will be
	 * set to the reference position) or <code>fIndent</code> will be set to
	 * the number of indentation units.
	 * </p>
	 *
	 * @param bound the bound for the search for the first token after the scope
	 * introduction.
	 * @return the indent
	 */
	private int handleScopeIntroduction(int bound) {
		switch (fToken) {
			// scope introduction: special treat who special is
			case Symbols.TokenLPAREN:
				int pos= fPosition; // store

				// special: method declaration deep indentation
				if (looksLikeMethodDecl()) {
					if (fPrefs.prefMethodDeclDeepIndent)
						return setFirstElementAlignment(pos, bound);
					else {
						fIndent= fPrefs.prefMethodDeclIndent;
						return pos;
					}
				} else {
					fPosition= pos;
					if (looksLikeMethodCall()) {
						if (fPrefs.prefMethodCallDeepIndent)
							return setFirstElementAlignment(pos, bound);
						else {
							fIndent= fPrefs.prefMethodCallIndent;
							return pos;
						}
					} else if (fPrefs.prefParenthesisDeepIndent)
						return setFirstElementAlignment(pos, bound);
				}

				// normal: return the parenthesis as reference
				fIndent= fPrefs.prefParenthesisIndent;
				return pos;

			case Symbols.TokenLBRACE:
				pos= fPosition; // store

				// special: array initializer
				if (looksLikeArrayInitializerIntro())
					if (fPrefs.prefArrayDeepIndent)
						return setFirstElementAlignment(pos, bound);
					else
						fIndent= fPrefs.prefArrayIndent;
				else
					fIndent= fPrefs.prefBlockIndent;

				// normal: skip to the statement start before the scope introducer
				// opening braces are often on differently ending indents than e.g. a method definition
				if (looksLikeArrayInitializerIntro() && !fPrefs.prefIndentBracesForArrays
						|| !fPrefs.prefIndentBracesForBlocks) {
					fPosition= pos; // restore
					return skipToStatementStart(true, true); // set to true to match the first if
				} else {
					return pos;
				}

			case Symbols.TokenLBRACKET:
				pos= fPosition; // store

				// special: method declaration deep indentation
				if (fPrefs.prefArrayDimensionsDeepIndent) {
					return setFirstElementAlignment(pos, bound);
				}

				// normal: return the bracket as reference
				fIndent= fPrefs.prefBracketIndent;
				return pos; // restore

			default:
				Assert.isTrue(false);
				return -1; // dummy
		}
	}

	/**
	 * Sets the deep indent offset (<code>fAlign</code>) to either the offset
	 * right after <code>scopeIntroducerOffset</code> or - if available - the
	 * first Java token after <code>scopeIntroducerOffset</code>, but before
	 * <code>bound</code>.
	 *
	 * @param scopeIntroducerOffset the offset of the scope introducer
	 * @param bound the bound for the search for another element
	 * @return the reference position
	 */
	private int setFirstElementAlignment(int scopeIntroducerOffset, int bound) {
		int firstPossible= scopeIntroducerOffset + 1; // align with the first position after the scope intro
		fAlign= fScanner.findNonWhitespaceForwardInAnyPartition(firstPossible, bound);
		if (fAlign == JavaHeuristicScanner.NOT_FOUND)
			fAlign= firstPossible;
		return fAlign;
	}


	/**
	 * Returns <code>true</code> if the next token received after calling
	 * <code>nextToken</code> is either an equal sign or an array designator ('[]').
	 *
	 * @return <code>true</code> if the next elements look like the start of an array definition
	 */
	private boolean looksLikeArrayInitializerIntro() {
		nextToken();
		if (fToken == Symbols.TokenEQUAL || skipBrackets()) {
			return true;
		}
		return false;
	}

	/**
	 * Skips over the next <code>if</code> keyword. The current token when calling
	 * this method must be an <code>else</code> keyword. Returns <code>true</code>
	 * if a matching <code>if</code> could be found, <code>false</code> otherwise.
	 * The cursor (<code>fPosition</code>) is set to the offset of the <code>if</code>
	 * token.
	 *
	 * @return <code>true</code> if a matching <code>if</code> token was found, <code>false</code> otherwise
	 */
	private boolean skipNextIF() {
		Assert.isTrue(fToken == Symbols.TokenELSE);

		while (true) {
			nextToken();
			switch (fToken) {
				// scopes: skip them
				case Symbols.TokenRPAREN:
				case Symbols.TokenRBRACKET:
				case Symbols.TokenRBRACE:
				case Symbols.TokenGREATERTHAN:
					skipScope();
					break;

				case Symbols.TokenIF:
					// found it, return
					return true;
				case Symbols.TokenELSE:
					// recursively skip else-if blocks
					skipNextIF();
					break;

				// shortcut scope starts
				case Symbols.TokenLPAREN:
				case Symbols.TokenLBRACE:
				case Symbols.TokenLBRACKET:
				case Symbols.TokenEOF:
					return false;
				}
		}
	}


	/**
	 * Skips over the next <code>try</code> keyword. The current token when calling this method must
	 * be a <code>catch</code> or <code>finally</code> keyword. Returns <code>true</code> if a
	 * matching <code>try</code> could be found, <code>false</code> otherwise. The cursor (
	 * <code>fPosition</code>) is set to the offset of the <code>try</code> token.
	 * 
	 * @return <code>true</code> if a matching <code>try</code> token was found, <code>false</code>
	 *         otherwise
	 * @since 3.7
	 */
	private boolean skipNextTRY() {
		Assert.isTrue(fToken == Symbols.TokenCATCH || fToken == Symbols.TokenFINALLY);
	
		while (true) {
			nextToken();
			switch (fToken) {
			// scopes: skip them
				case Symbols.TokenRPAREN:
				case Symbols.TokenRBRACKET:
				case Symbols.TokenRBRACE:
				case Symbols.TokenGREATERTHAN:
					skipScope();
					break;
	
				case Symbols.TokenTRY:
					// found it
					return true;
	
					// shortcut scope starts
				case Symbols.TokenLPAREN:
				case Symbols.TokenLBRACE:
				case Symbols.TokenLBRACKET:
				case Symbols.TokenEOF:
					return false;
			}
		}
	}

	/**
	 * while(condition); is ambiguous when parsed backwardly, as it is a valid
	 * statement by its own, so we have to check whether there is a matching
	 * do. A <code>do</code> can either be separated from the while by a
	 * block, or by a single statement, which limits our search distance.
	 *
	 * @return <code>true</code> if the <code>while</code> currently in
	 *         <code>fToken</code> has a matching <code>do</code>.
	 */
	private boolean hasMatchingDo() {
		Assert.isTrue(fToken == Symbols.TokenWHILE);
		nextToken();
		switch (fToken) {
			case Symbols.TokenRBRACE:
				skipScope();
				//$FALL-THROUGH$
			case Symbols.TokenSEMICOLON:
				skipToStatementStart(false, false);
				return fToken == Symbols.TokenDO;
		}
		return false;
	}

	/**
	 * Skips brackets if the current token is a RBRACKET. There can be nothing
	 * but whitespace in between, this is only to be used for <code>[]</code> elements.
	 *
	 * @return <code>true</code> if a <code>[]</code> could be scanned, the
	 *         current token is left at the LBRACKET.
	 */
	private boolean skipBrackets() {
		if (fToken == Symbols.TokenRBRACKET) {
			nextToken();
			if (fToken == Symbols.TokenLBRACKET) {
				return true;
			}
		}
		return false;
	}

	/**
	 * Reads the next token in backward direction from the heuristic scanner
	 * and sets the fields <code>fToken, fPreviousPosition</code> and <code>fPosition</code>
	 * accordingly.
	 */
	private void nextToken() {
		nextToken(fPosition);
	}

	/**
	 * Reads the next token in backward direction of <code>start</code> from
	 * the heuristic scanner and sets the fields <code>fToken, fPreviousPosition</code>
	 * and <code>fPosition</code> accordingly.
	 *
	 * @param start the start offset from which to scan backwards
	 */
	private void nextToken(int start) {
		fToken= fScanner.previousToken(start - 1, JavaHeuristicScanner.UNBOUND);
		fPreviousPos= start;
		fPosition= fScanner.getPosition() + 1;
		try {
			fLine= fDocument.getLineOfOffset(fPosition);
		} catch (BadLocationException e) {
			fLine= -1;
		}
	}

	/**
	 * Returns <code>true</code> if the current tokens look like a method
	 * declaration header (i.e. only the return type and method name). The
	 * heuristic calls <code>nextToken</code> and expects an identifier
	 * (method name) and a type declaration (an identifier with optional
	 * brackets) which also covers the visibility modifier of constructors; it
	 * does not recognize package visible constructors.
	 *
	 * @return <code>true</code> if the current position looks like a method
	 *         declaration header.
	 */
	private boolean looksLikeMethodDecl() {
		/*
		 * TODO This heuristic does not recognize package private constructors
		 * since those do have neither type nor visibility keywords.
		 * One option would be to go over the parameter list, but that might
		 * be empty as well, or not typed in yet - hard to do without an AST...
		 */

		nextToken();
		if (fToken == Symbols.TokenIDENT) { // method name
			do nextToken();
			while (skipBrackets()); // optional brackets for array valued return types

			return fToken == Symbols.TokenIDENT; // return type name

		}
		return false;
	}

	/**
	 * Returns <code>true</code> if the current tokens look like an annotation (i.e. an annotation
	 * name (potentially qualified) preceded by an at-sign).
	 * 
	 * @return <code>true</code> if the current position looks like an annotation.
	 * @since 3.7
	 */

	private boolean looksLikeAnnotation() {
		nextToken();
		if (fToken == Symbols.TokenIDENT) { // Annotation name
			nextToken();
			while (fToken == Symbols.TokenOTHER) { // dot of qualification
				nextToken();
				if (fToken != Symbols.TokenIDENT) // qualifying name
					return false;
				nextToken();
			}
			return fToken == Symbols.TokenAT;
		}
		return false;
	}
	
	/**
	 * Returns <code>true</code> if the current tokens look like an anonymous type declaration
	 * header (i.e. a type name (potentially qualified) and a new keyword). The heuristic calls
	 * <code>nextToken</code> and expects a possibly qualified identifier (type name) and a new
	 * keyword
	 *
	 * @return <code>true</code> if the current position looks like a anonymous type declaration
	 *         header.
	 */
	private boolean looksLikeAnonymousTypeDecl() {

		nextToken();
		if (fToken == Symbols.TokenIDENT) { // type name
			nextToken();
			while (fToken == Symbols.TokenOTHER) { // dot of qualification
				nextToken();
				if (fToken != Symbols.TokenIDENT) // qualifying name
					return false;
				nextToken();
			}
			return fToken == Symbols.TokenNEW;
		}
		return false;
	}

	/**
	 * Returns <code>true</code> if the current tokens look like a method
	 * call header (i.e. an identifier as opposed to a keyword taking parenthesized
	 * parameters such as <code>if</code>).
	 * <p>The heuristic calls <code>nextToken</code> and expects an identifier
	 * (method name).
	 *
	 * @return <code>true</code> if the current position looks like a method call
	 *         header.
	 */
	private boolean looksLikeMethodCall() {
		// TODO [5.0] add awareness for constructor calls with generic types: new ArrayList<String>()
		nextToken();
		return fToken == Symbols.TokenIDENT; // method name
	}

	/**
	 * Scans tokens for the matching opening peer. The internal cursor
	 * (<code>fPosition</code>) is set to the offset of the opening peer if found.
	 *
	 * @param openToken the opening peer token
	 * @param closeToken the closing peer token
	 * @return <code>true</code> if a matching token was found, <code>false</code>
	 *         otherwise
	 */
	private boolean skipScope(int openToken, int closeToken) {

		int depth= 1;

		while (true) {
			nextToken();

			if (fToken == closeToken) {
				depth++;
			} else if (fToken == openToken) {
				depth--;
				if (depth == 0)
					return true;
			} else if (fToken == Symbols.TokenEOF) {
					return false;
			}
		}
	}
}
