/*******************************************************************************
 * Copyright (c) 2000, 2020 IBM Corporation 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:
 *     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 static 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 prefContinuationIndentForArrayInitializer(); // 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 int prefContinuationIndentForArrayInitializer() {
			try {
				return Integer.parseInt(getCoreFormatterOption(DefaultCodeFormatterConstants.FORMATTER_CONTINUATION_INDENTATION_FOR_ARRAY_INITIALIZER));
			} catch (NumberFormatException e) {
				// ignore and return default
			}

			return 2; // sensible default
		}
		private boolean hasGenerics() {
			return JavaCore.compareJavaVersions(JavaCore.VERSION_1_5, 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 scan position of most resent token. */
	private int fTokenPos;
	/**
	 * 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)
				|| 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;

				switch (nextToken) {
					case Symbols.TokenELSE:
						danglingElse= true;
						break;
					case Symbols.TokenDEFAULT:
						fScanner.nextToken(offset, lineOffset + line.getLength());
						int next= fScanner.nextToken(fScanner.getPosition(), JavaHeuristicScanner.UNBOUND);
						if (next != Symbols.TokenCOLON) {
							break;
						}
						//$FALL-THROUGH$
					case Symbols.TokenCASE:
						if (isFirstTokenOnLine)
							matchCase= true;
						break;
					case Symbols.TokenLBRACE: // for opening-brace-on-new-line style
						int prevToken= fScanner.previousToken(prevPos, JavaHeuristicScanner.UNBOUND);
						boolean bracelessBlockStart= fScanner.isBracelessBlockStart(prevPos, JavaHeuristicScanner.UNBOUND);
						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 (nextNonWSCharPosition != JavaHeuristicScanner.NOT_FOUND && 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 - lineOfToken()) > 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 - lineOfToken()) == 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.getLineInformationOfOffset(fTokenPos).getOffset();
					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();
		}

		int storedPos= fPosition;
		if (peekChar(offset) == Symbols.TokenLBRACE && looksLikeMethodDeclLBrace(offset)) {
			return skipToStatementStart(danglingElse, false);
		}
		fPosition= storedPos;

		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;
					}
					fPosition= pos;
					if (isSemicolonPartOfEnumBodyDeclaration()) {
						fIndent= getBlockIndent(false, true);
						return fPosition;
					}
					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:
			case Symbols.TokenRETURN:
				fIndent= fPrefs.prefContinuationIndent;
				return fPosition;

			case Symbols.TokenRPAREN:
				if (throwsClause) {
					fIndent= fPrefs.prefContinuationIndent;
					return fPosition;
				}
				int rParen= fPosition;
				int tokenPos = fTokenPos;
				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 (fToken == Symbols.TokenCATCH) {
						return skipToStatementStart(danglingElse, false);
					}
					fPosition= scope;
					if (looksLikeAnonymousTypeDecl(rParen)) {
						return skipToStatementStart(danglingElse, false);
					}
					fPosition= scope;
					if (looksLikeAnnotation()) {
						return skipToStatementStart(danglingElse, false);
					}
					fPosition= scope;
					if (looksLikeStringContinuation()) {
						return fPosition;
					}
				}
				// restore
				fPosition= offset;
				fTokenPos = tokenPos;

				return skipToPreviousListItemOrListStart();
		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 whether the Symbols.TokenLBRACE after <code>offset</code> probably represents the
	 * beginning of a method body declaration.
	 *
	 * @param offset the document offset for which {@link #peekChar(int) peekChar(offset)} returns
	 *            Symbols.TokenLBRACE
	 * @return <code>true</code> if the left brace after <code>offset</code> looks like the
	 *         beginning of a method body declaration, <code>false</code> otherwise
	 *
	 * @since 3.9
	 */
	private boolean looksLikeMethodDeclLBrace(int offset) {
		nextToken();
		while (true) {
			switch (fToken) {
				case Symbols.TokenTHROWS:
				case Symbols.TokenIDENT: // identifier for exception/annotation/annotation value
				case Symbols.TokenCOMMA:
				case Symbols.TokenAT:
				case Symbols.TokenLBRACKET: // for array valued return type
				case Symbols.TokenRBRACKET:
					break; // possible tokens between '{' and ')' in method declaration
				case Symbols.TokenOTHER: // dot of qualification
					try {
						if (fDocument.getChar(fPosition) != '.') {
							return false;
						}
					} catch (BadLocationException e) {
						return false;
					}
					break;
				case Symbols.TokenRPAREN: // parenthesis for annotation value / method declaration
					skipScope();
					int storedPos= fPosition;
					if (looksLikeMethodDecl())
						return true;
					fPosition= storedPos;
					break;
				case Symbols.TokenEOF:
			default:
				return false;
			}
			nextToken();
		}
	}

	/**
	 * 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:
				case Symbols.TokenCOLON:
				case Symbols.TokenEOF:
					return false;
				case Symbols.TokenSEMICOLON:
					semiColonCount++;
					if (semiColonCount > 2)
						return false;
					break;
			}
		}
	}

	/**
	 * 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:
				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;
					int pos2= fPosition;
					if (!isConditional())
						return pos;
					fPosition= pos2;
					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= lineOfToken();
		int startPosition= fPosition;
		while (true) {
			nextToken();

			// if any line item comes with its own indentation, adapt to it
			if (lineOfToken() < 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();
					startLine= lineOfToken();
					startPosition= fPosition;
					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.TokenLESSTHAN:
						return true;
					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;
						return pos;
					}
				} 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 ('[]') preceded by array creation.
	 *
	 * @return <code>true</code> if the next elements look like the start of an array definition
	 */
	private boolean looksLikeArrayInitializerIntro() {
		nextToken();
		if (fToken == Symbols.TokenEQUAL) {
			return true;
		}

		if (!skipScope(Symbols.TokenLBRACKET, Symbols.TokenRBRACKET)) {
			return false;
		}
		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 position looks like a part of enum declaration
	 * header. It calls {@link #nextToken} to scan backwards.
	 *
	 * @return <code>true</code> if the current position looks like a part of enum declaration
	 *         header
	 * @since 3.11
	 */
	private boolean looksLikeEnumDeclaration() {
		while (true) {
			nextToken();
			switch (fToken) {
				case Symbols.TokenENUM:
					return true;
				case Symbols.TokenIDENT:
				case Symbols.TokenCOMMA:
				case Symbols.TokenAT:
					break;
				case Symbols.TokenOTHER:
					try {
						if (fDocument.getChar(fPosition) != '.') {
							return false;
						}
					} catch (BadLocationException e) {
						return false;
					}
					break;
				case Symbols.TokenRPAREN:
				case Symbols.TokenRBRACKET:
				case Symbols.TokenRBRACE:
				case Symbols.TokenGREATERTHAN:
					skipScope();
					break;
				case Symbols.TokenEOF:
				default:
					return false;
			}
		}
	}

	/**
	 * Checks if the semicolon at the current position is part of enum body declaration.
	 *
	 * @return returns <code>true</code> if the semicolon at the current position is part of enum
	 *         body declaration
	 * @since 3.11
	 */
	private boolean isSemicolonPartOfEnumBodyDeclaration() {
		while (true) {
			nextToken();
			switch (fToken) {
				case Symbols.TokenLBRACE:
					return looksLikeEnumDeclaration();
				case Symbols.TokenIDENT:
				case Symbols.TokenCOMMA:
					break;
				case Symbols.TokenRPAREN:
				case Symbols.TokenRBRACKET:
				case Symbols.TokenRBRACE:
				case Symbols.TokenGREATERTHAN:
					skipScope();
					break;
				case Symbols.TokenEOF:
				default:
					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, fTokenPos, 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, fTokenPos, 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;
		fTokenPos = fPosition;
	}

	/**
	 * Get line in document for most recent token.
	 *
	 * @return document line for <code>fTokenPos</code> or <code>-1</code> if invalid
	 */
	private int lineOfToken() {
		try {
			return fDocument.getLineOfOffset(fTokenPos);
		} catch (BadLocationException e) {
			return -1;
		}
	}

	/**
	 * Checks whether the current position represents a method call in string continuation. The
	 * current token should represent the left parenthesis of method call.
	 *
	 * @return <code>true</code> if the current position looks like a method call in string
	 *         continuation, <code>false</code> otherwise
	 * @since 3.11
	 */
	private boolean looksLikeStringContinuation() {
		nextToken();
		if (fToken == Symbols.TokenIDENT) { // method name
			nextToken();
			if (fToken == Symbols.TokenGREATERTHAN) { // type arguments
				skipScope(Symbols.TokenLESSTHAN, Symbols.TokenGREATERTHAN);
				nextToken();
			}
			while (fToken == Symbols.TokenOTHER) { // dot of qualification
				nextToken();
				if (fToken != Symbols.TokenIDENT) // qualifying name
					return false;
				nextToken();
			}
			if (fToken == Symbols.TokenRPAREN) { // cast
				skipScope(Symbols.TokenLPAREN, Symbols.TokenRPAREN);
				nextToken();
			}
			return fToken == Symbols.TokenPLUS;
		}
		return false;
	}

	/**
	 * 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
			if (fToken == Symbols.TokenGREATERTHAN) {
				if (skipScope(Symbols.TokenLESSTHAN, Symbols.TokenGREATERTHAN)) { // parameterized return type
					nextToken();
				} else {
					return false;
				}
			}
			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
	 *
	 * @param rParen offset of the right parenthesis
	 *
	 * @return <code>true</code> if the current position looks like a anonymous type declaration
	 *         header.
	 */
	private boolean looksLikeAnonymousTypeDecl(int rParen) {
		try {
			int nonWsFwd= fScanner.findNonWhitespaceForwardInAnyPartition(rParen + 1, JavaHeuristicScanner.UNBOUND);
			if (nonWsFwd == JavaHeuristicScanner.NOT_FOUND || fDocument.getChar(nonWsFwd) != '{') {
				return false;
			}
		} catch (BadLocationException e) {
			return false;
		}
		nextToken();
		if (fToken == Symbols.TokenGREATERTHAN) {
			if (skipScope(Symbols.TokenLESSTHAN, Symbols.TokenGREATERTHAN)) { // parameterized type
				nextToken();
			} else {
				return false;
			}
		}
		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;
			}
		}
	}
}
