/*******************************************************************************
 * 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.java;

import java.util.Arrays;

import org.eclipse.core.runtime.Assert;

import org.eclipse.text.edits.DeleteEdit;
import org.eclipse.text.edits.MalformedTreeException;
import org.eclipse.text.edits.ReplaceEdit;
import org.eclipse.text.edits.TextEdit;

import org.eclipse.jface.preference.IPreferenceStore;

import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.DocumentCommand;
import org.eclipse.jface.text.IAutoEditStrategy;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.text.ITypedRegion;
import org.eclipse.jface.text.Region;
import org.eclipse.jface.text.TextSelection;
import org.eclipse.jface.text.TextUtilities;

import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IWorkbenchPage;

import org.eclipse.ui.texteditor.ITextEditorExtension2;
import org.eclipse.ui.texteditor.ITextEditorExtension3;

import org.eclipse.jdt.ui.PreferenceConstants;
import org.eclipse.jdt.ui.text.IJavaPartitions;

import org.eclipse.jdt.internal.ui.JavaPlugin;
import org.eclipse.jdt.internal.ui.javaeditor.CompilationUnitEditor;
import org.eclipse.jdt.internal.ui.text.SmartBackspaceManager;
import org.eclipse.jdt.internal.ui.text.SmartBackspaceManager.UndoSpec;

/**
 * Modifies <code>DocumentCommand</code>s inserting semicolons and opening braces to place them
 * smartly, i.e. moving them to the end of a line if that is what the user expects.
 *
 * <p>In practice,  semicolons and braces (and the caret) are moved to the end of the line if they are typed
 * anywhere except for semicolons in a <code>for</code> statements definition. If the line contains a semicolon
 * or brace after the current caret position, the cursor is moved after it.</p>
 *
 * @see org.eclipse.jface.text.DocumentCommand
 * @since 3.0
 */
public class SmartSemicolonAutoEditStrategy implements IAutoEditStrategy {

	/** String representation of a semicolon. */
	private static final String SEMICOLON= ";"; //$NON-NLS-1$
	/** Char representation of a semicolon. */
	private static final char SEMICHAR= ';';
	/** String represenattion of a opening brace. */
	private static final String BRACE= "{"; //$NON-NLS-1$
	/** Char representation of a opening brace */
	private static final char BRACECHAR= '{';

	private char fCharacter;
	private String fPartitioning;

	/**
	 * Creates a new SmartSemicolonAutoEditStrategy.
	 *
	 * @param partitioning the document partitioning
	 */
	public SmartSemicolonAutoEditStrategy(String partitioning) {
		fPartitioning= partitioning;
	}

	/*
	 * @see org.eclipse.jface.text.IAutoEditStrategy#customizeDocumentCommand(org.eclipse.jface.text.IDocument, org.eclipse.jface.text.DocumentCommand)
	 */
	@Override
	public void customizeDocumentCommand(IDocument document, DocumentCommand command) {
		// 0: early pruning
		// also customize if <code>doit</code> is false (so it works in code completion situations)
		//		if (!command.doit)
		//			return;

		if (command.text == null)
			return;

		if (command.text.equals(SEMICOLON))
			fCharacter= SEMICHAR;
		else if (command.text.equals(BRACE))
			fCharacter= BRACECHAR;
		else
			return;

		IPreferenceStore store= JavaPlugin.getDefault().getPreferenceStore();
		if (fCharacter == SEMICHAR && !store.getBoolean(PreferenceConstants.EDITOR_SMART_SEMICOLON))
			return;
		if (fCharacter == BRACECHAR && !store.getBoolean(PreferenceConstants.EDITOR_SMART_OPENING_BRACE))
			return;

		IWorkbenchPage page= JavaPlugin.getActivePage();
		if (page == null)
			return;
		IEditorPart part= page.getActiveEditor();
		if (!(part instanceof CompilationUnitEditor))
			return;
		CompilationUnitEditor editor= (CompilationUnitEditor)part;
		if (editor.getInsertMode() != ITextEditorExtension3.SMART_INSERT || !editor.isEditable())
			return;
		ITextEditorExtension2 extension= editor.getAdapter(ITextEditorExtension2.class);
		if (extension != null && !extension.validateEditorInputState())
			return;
		if (isMultilineSelection(document, command))
			return;

		// 1: find concerned line / position in java code, location in statement
		int pos= command.offset;
		ITextSelection line;
		try {
			IRegion l= document.getLineInformationOfOffset(pos);
			line= new TextSelection(document, l.getOffset(), l.getLength());
		} catch (BadLocationException e) {
			return;
		}

		// 2: choose action based on findings (is for-Statement?)
		// for now: compute the best position to insert the new character
		int positionInLine= computeCharacterPosition(document, line, pos - line.getOffset(), fCharacter, fPartitioning);
		int position= positionInLine + line.getOffset();

		// never position before the current position!
		if (position < pos)
			return;

		// never double already existing content
		if (alreadyPresent(document, fCharacter, position))
			return;

		// don't do special processing if what we do is actually the normal behaviour
		String insertion= adjustSpacing(document, position, fCharacter);
		if (command.offset == position && insertion.equals(command.text))
			return;

		try {

			final SmartBackspaceManager manager= editor.getAdapter(SmartBackspaceManager.class);
			if (manager != null && JavaPlugin.getDefault().getPreferenceStore().getBoolean(PreferenceConstants.EDITOR_SMART_BACKSPACE)) {
				TextEdit e1= new ReplaceEdit(command.offset, command.text.length(), document.get(command.offset, command.length));
				UndoSpec s1= new UndoSpec(command.offset + command.text.length(),
						new Region(command.offset, 0),
						new TextEdit[] {e1},
						0,
						null);

				DeleteEdit smart= new DeleteEdit(position, insertion.length());
				ReplaceEdit raw= new ReplaceEdit(command.offset, command.length, command.text);
				UndoSpec s2= new UndoSpec(position + insertion.length(),
						new Region(command.offset + command.text.length(), 0),
						new TextEdit[] {smart, raw},
						2,
						s1);
				manager.register(s2);
			}

			// 3: modify command
			command.offset= position;
			command.length= 0;
			command.caretOffset= position;
			command.text= insertion;
			command.doit= true;
			command.owner= null;
		} catch (MalformedTreeException | BadLocationException e) {
			JavaPlugin.log(e);
		}


	}

	/**
	 * Returns <code>true</code> if the document command is applied on a multi
	 * line selection, <code>false</code> otherwise.
	 *
	 * @param document the document
	 * @param command the command
	 * @return <code>true</code> if <code>command</code> is a multiline command
	 */
	private boolean isMultilineSelection(IDocument document, DocumentCommand command) {
		try {
			return document.getNumberOfLines(command.offset, command.length) > 1;
		} catch (BadLocationException e) {
			// ignore
			return false;
		}
	}

	/**
	 * Adds a space before a brace if it is inserted after a parenthesis, equal sign, or one
	 * of the keywords <code>try, else, do</code>.
	 *
	 * @param doc the document we are working on
	 * @param position the insert position of <code>character</code>
	 * @param character the character to be inserted
	 * @return a <code>String</code> consisting of <code>character</code> plus any additional spacing
	 */
	private String adjustSpacing(IDocument doc, int position, char character) {
		if (character == BRACECHAR) {
			if (position > 0 && position <= doc.getLength()) {
				int pos= position - 1;
				if (looksLike(doc, pos, ")") //$NON-NLS-1$
				|| looksLike(doc, pos, "=") //$NON-NLS-1$
				|| looksLike(doc, pos, "]") //$NON-NLS-1$
				|| looksLike(doc, pos, "try") //$NON-NLS-1$
				|| looksLike(doc, pos, "else") //$NON-NLS-1$
				|| looksLike(doc, pos, "synchronized") //$NON-NLS-1$
				|| looksLike(doc, pos, "static") //$NON-NLS-1$
				|| looksLike(doc, pos, "finally") //$NON-NLS-1$
				|| looksLike(doc, pos, "do")) //$NON-NLS-1$
					return new String(new char[] { ' ', character });
			}
		}

		return new String(new char[] { character });
	}

	/**
	 * Checks whether a character to be inserted is already present at the insert location (perhaps
	 * separated by some whitespace from <code>position</code>.
	 *
	 * @param document the document we are working on
	 * @param position the insert position of <code>ch</code>
	 * @param ch the character to be inserted
	 * @return <code>true</code> if <code>ch</code> is already present at <code>location</code>, <code>false</code> otherwise
	 */
	private boolean alreadyPresent(IDocument document, char ch, int position) {
		int pos= firstNonWhitespaceForward(document, position, fPartitioning, document.getLength());
		try {
			if (pos != -1 && document.getChar(pos) == ch)
				return true;
		} catch (BadLocationException e) {
		}

		return false;
	}

	/**
	 * Computes the next insert position of the given character in the current line.
	 *
	 * @param document the document we are working on
	 * @param line the line where the change is being made
	 * @param offset the position of the caret in the line when <code>character</code> was typed
	 * @param character the character to look for
	 * @param partitioning the document partitioning
	 * @return the position where <code>character</code> should be inserted / replaced
	 */
	protected static int computeCharacterPosition(IDocument document, ITextSelection line, int offset, char character, String partitioning) {
		String text= line.getText();
		if (text == null)
			return 0;

		if (!isDefaultPartition(document, offset + line.getOffset(),partitioning)) {
			return -1;
		}

		int insertPos;
		switch (character) {
		case BRACECHAR:
			insertPos= computeArrayInitializationPos(document, line, offset, partitioning);
			if (insertPos == -1) {
				insertPos= computeAfterTryDoElse(document, line, offset);
			}
			if (insertPos == -1) {
				insertPos= computeAfterLambdaArrow(document, line, offset, partitioning);
			}
			if (insertPos == -1) {
				insertPos= computeAfterParenthesis(document, line, offset, partitioning);
			}
			break;
		case SEMICHAR:
			if (isForStatement(text, offset)) {
				insertPos= -1; // don't do anything in for statements, as semis are vital part of these
			} else {
				int nextPartitionPos= nextPartitionOrLineEnd(document, line, offset, partitioning);
				insertPos= startOfWhitespaceBeforeOffset(text, nextPartitionPos);
				// if there is a semi present, return its location as alreadyPresent() will take it out this way.
				if (insertPos > 0 && text.charAt(insertPos - 1) == character)
					insertPos= insertPos - 1;
				else if (insertPos > 0 && text.charAt(insertPos - 1) == '}') {
					int opening= scanBackward(document, insertPos - 1 + line.getOffset(), partitioning, -1, new char[] { '{' });
					if (opening > -1 && opening < offset + line.getOffset()) {
						if (computeArrayInitializationPos(document, line, opening - line.getOffset(), partitioning) == -1) {
							insertPos= offset;
						}
					}
				}
			}
			break;
		default:
			Assert.isTrue(false);
			return -1;
		}

		return insertPos;
	}

	/**
	 * Computes an insert position for an opening brace if <code>offset</code> maps to a position in
	 * <code>document</code> that looks like being the RHS of an assignment or like an array definition.
	 *
	 * @param document the document being modified
	 * @param line the current line under investigation
	 * @param offset the offset of the caret position, relative to the line start.
	 * @param partitioning the document partitioning
	 * @return an insert position  relative to the line start if <code>line</code> looks like being an array initialization at <code>offset</code>, -1 otherwise
	 */
	private static int computeArrayInitializationPos(IDocument document, ITextSelection line, int offset, String partitioning) {
		// search backward while WS, find = (not != <= >= ==) in default partition
		int pos= offset + line.getOffset();

		if (pos == 0)
			return -1;

		int p= firstNonWhitespaceBackward(document, pos - 1, partitioning, -1);

		if (p == -1)
			return -1;

		try {

			char ch= document.getChar(p);
			if (ch != '=' && ch != ']')
				return -1;

			if (p == 0)
				return offset;

			p= firstNonWhitespaceBackward(document, p - 1, partitioning, -1);
			if (p == -1)
				return -1;

			ch= document.getChar(p);
			if (Character.isJavaIdentifierPart(ch) || ch == ']' || ch == '[')
				return offset;

		} catch (BadLocationException e) {
		}
		return -1;
	}

	/**
	 * Computes an insert position for an opening brace if <code>offset</code> maps to a position in
	 * <code>doc</code> involving a keyword taking a block after it. These are: <code>try</code>,
	 * <code>do</code>, <code>synchronized</code>, <code>static</code>, <code>finally</code>, or <code>else</code>.
	 *
	 * @param doc the document being modified
	 * @param line the current line under investigation
	 * @param offset the offset of the caret position, relative to the line start.
	 * @return an insert position  relative to the line start if <code>line</code> contains one of the above keywords at or before <code>offset</code>, -1 otherwise
	 */
	private static int computeAfterTryDoElse(IDocument doc, ITextSelection line, int offset) {
		// search backward while WS, find 'try', 'do', 'else' in default partition
		int p= offset + line.getOffset();
		p= firstWhitespaceToRight(doc, p);
		if (p == -1)
			return -1;
		p--;

		if (looksLike(doc, p, "try") //$NON-NLS-1$
				|| looksLike(doc, p, "do")  //$NON-NLS-1$
				|| looksLike(doc, p, "synchronized")  //$NON-NLS-1$
				|| looksLike(doc, p, "static")  //$NON-NLS-1$
				|| looksLike(doc, p, "finally")  //$NON-NLS-1$
				|| looksLike(doc, p, "else"))  //$NON-NLS-1$
			return p + 1 - line.getOffset();

		return -1;
	}

	/**
	 * Computes an insert position for an opening brace if <code>offset</code> maps to a position immediately after a lambda arrow.
	 *
	 * @param doc the document being modified
	 * @param line the current line under investigation
	 * @param offset the offset of the caret position, relative to the line start.
	 * @param partitioning the document partitioning
	 * @return an insert position relative to the line start if <code>line</code> contains a lambda arrow at or before <code>offset</code>, -1 otherwise
	 */
	private static int computeAfterLambdaArrow(IDocument doc, ITextSelection line, int offset, String partitioning)  {
		int absoluteOffset= offset + line.getOffset();
		int p= firstNonWhitespaceBackward(doc, absoluteOffset - 1, partitioning, -1);
		if (p <= 0)
			return -1;

		try {
			if (doc.get(p - 1, 2).equals("->")) { //$NON-NLS-1$
				return offset;
			}
		} catch (BadLocationException e) {
		}

		return -1;
	}

	/**
	 * Computes an insert position for an opening brace if <code>offset</code> maps to a position in
	 * <code>document</code> with a expression in parenthesis that will take a block after the closing parenthesis.
	 *
	 * @param document the document being modified
	 * @param line the current line under investigation
	 * @param offset the offset of the caret position, relative to the line start.
	 * @param partitioning the document partitioning
	 * @return an insert position relative to the line start if <code>line</code> contains a parenthesized expression that can be followed by a block, -1 otherwise
	 */
	private static int computeAfterParenthesis(IDocument document, ITextSelection line, int offset, String partitioning) {
		// find the opening parenthesis for every closing parenthesis on the current line after offset
		// return the position behind the closing parenthesis if it looks like a method declaration
		// or an expression for an if, while, for, catch statement
		int pos= offset + line.getOffset();
		int length= line.getOffset() + line.getLength();
		int scanTo= scanForward(document, pos, partitioning, length, '}');
		if (scanTo == -1)
			scanTo= length;

		int closingParen= findClosingParenToLeft(document, pos, partitioning) - 1;

		while (true) {
			int startScan= closingParen + 1;
			closingParen= scanForward(document, startScan, partitioning, scanTo, ')');
			if (closingParen == -1)
				break;

			int openingParen= findOpeningParenMatch(document, closingParen, partitioning);

			// no way an expression at the beginning of the document can mean anything
			if (openingParen < 1)
				break;

			// only select insert positions for parenthesis currently embracing the caret
			if (openingParen > pos)
				continue;

			if (looksLikeAnonymousClassDef(document, openingParen - 1, partitioning))
				return closingParen + 1 - line.getOffset();

			if (looksLikeIfWhileForCatch(document, openingParen - 1, partitioning))
				return closingParen + 1 - line.getOffset();

			if (looksLikeMethodDecl(document, openingParen - 1, partitioning))
				return closingParen + 1 - line.getOffset();

		}

		return -1;
	}

	/**
	 * Finds a closing parenthesis to the left of <code>position</code> in document, where that parenthesis is only
	 * separated by whitespace from <code>position</code>. If no such parenthesis can be found, <code>position</code> is returned.
	 *
	 * @param document the document being modified
	 * @param position the first character position in <code>document</code> to be considered
	 * @param partitioning the document partitioning
	 * @return the position of a closing parenthesis left to <code>position</code> separated only by whitespace, or <code>position</code> if no parenthesis can be found
	 */
	private static int findClosingParenToLeft(IDocument document, int position, String partitioning) {
		final char CLOSING_PAREN= ')';
		try {
			if (position < 1)
				return position;

			int nonWS= firstNonWhitespaceBackward(document, position - 1, partitioning, -1);
			if (nonWS != -1 && document.getChar(nonWS) == CLOSING_PAREN)
				return nonWS;
		} catch (BadLocationException e1) {
		}
		return position;
	}

	/**
	 * Finds the first whitespace character position to the right of (and including) <code>position</code>.
	 *
	 * @param document the document being modified
	 * @param position the first character position in <code>document</code> to be considered
	 * @return the position of a whitespace character greater or equal than <code>position</code> separated only by whitespace, or -1 if none found
	 */
	private static int firstWhitespaceToRight(IDocument document, int position) {
		int length= document.getLength();
		Assert.isTrue(position >= 0);
		Assert.isTrue(position <= length);

		try {
			while (position < length) {
				char ch= document.getChar(position);
				if (Character.isWhitespace(ch))
					return position;
				position++;
			}
			return position;
		} catch (BadLocationException e) {
		}
		return -1;
	}

	/**
	 * Finds the highest position in <code>document</code> such that the position is &lt;= <code>position</code>
	 * and &gt; <code>bound</code> and <code>Character.isWhitespace(document.getChar(pos))</code> evaluates to <code>false</code>
	 * and the position is in the default partition.
	 *
	 * @param document the document being modified
	 * @param position the first character position in <code>document</code> to be considered
	 * @param partitioning the document partitioning
	 * @param bound the first position in <code>document</code> to not consider any more, with <code>bound</code> &lt; <code>position</code>
	 * @return the highest position of one element in <code>chars</code> in [<code>position</code>, <code>scanTo</code>) that resides in a Java partition, or <code>-1</code> if none can be found
	 */
	private static int firstNonWhitespaceBackward(IDocument document, int position, String partitioning, int bound) {
		Assert.isTrue(position < document.getLength());
		Assert.isTrue(bound >= -1);

		try {
			while (position > bound) {
				char ch= document.getChar(position);
				if (!Character.isWhitespace(ch) && isDefaultPartition(document, position, partitioning))
					return position;
				position--;
			}
		} catch (BadLocationException e) {
		}
		return -1;
	}

	/**
	 * Finds the smallest position in <code>document</code> such that the position is &gt;= <code>position</code>
	 * and &lt; <code>bound</code> and <code>Character.isWhitespace(document.getChar(pos))</code> evaluates to <code>false</code>
	 * and the position is in the default partition.
	 *
	 * @param document the document being modified
	 * @param position the first character position in <code>document</code> to be considered
	 * @param partitioning the document partitioning
	 * @param bound the first position in <code>document</code> to not consider any more, with <code>bound</code> &gt; <code>position</code>
	 * @return the smallest position of one element in <code>chars</code> in [<code>position</code>, <code>scanTo</code>) that resides in a Java partition, or <code>-1</code> if none can be found
	 */
	private static int firstNonWhitespaceForward(IDocument document, int position, String partitioning, int bound) {
		Assert.isTrue(position >= 0);
		Assert.isTrue(bound <= document.getLength());

		try {
			while (position < bound) {
				char ch= document.getChar(position);
				if (!Character.isWhitespace(ch) && isDefaultPartition(document, position, partitioning))
					return position;
				position++;
			}
		} catch (BadLocationException e) {
		}
		return -1;
	}

	/**
	 * Finds the highest position in <code>document</code> such that the position is &lt;= <code>position</code>
	 * and &gt; <code>bound</code> and <code>document.getChar(position) == ch</code> evaluates to <code>true</code> for at least one
	 * ch in <code>chars</code> and the position is in the default partition.
	 *
	 * @param document the document being modified
	 * @param position the first character position in <code>document</code> to be considered
	 * @param partitioning the document partitioning
	 * @param bound the first position in <code>document</code> to not consider any more, with <code>scanTo</code> &gt; <code>position</code>
	 * @param chars an array of <code>char</code> to search for
	 * @return the highest position of one element in <code>chars</code> in (<code>bound</code>, <code>position</code>] that resides in a Java partition, or <code>-1</code> if none can be found
	 */
	private static int scanBackward(IDocument document, int position, String partitioning, int bound, char[] chars) {
		Assert.isTrue(bound >= -1);
		Assert.isTrue(position < document.getLength() );

		Arrays.sort(chars);

		try {
			while (position > bound) {

				if (Arrays.binarySearch(chars, document.getChar(position)) >= 0 && isDefaultPartition(document, position, partitioning))
					return position;

				position--;
			}
		} catch (BadLocationException e) {
		}
		return -1;
	}

//	/**
//	 * Finds the highest position in <code>document</code> such that the position is &lt;= <code>position</code>
//	 * and &gt; <code>bound</code> and <code>document.getChar(position) == ch</code> evaluates to <code>true</code>
//	 * and the position is in the default partition.
//	 *
//	 * @param document the document being modified
//	 * @param position the first character position in <code>document</code> to be considered
//	 * @param bound the first position in <code>document</code> to not consider any more, with <code>scanTo</code> &gt; <code>position</code>
//	 * @param chars an array of <code>char</code> to search for
//	 * @return the highest position of one element in <code>chars</code> in [<code>position</code>, <code>scanTo</code>) that resides in a Java partition, or <code>-1</code> if none can be found
//	 */
//	private static int scanBackward(IDocument document, int position, int bound, char ch) {
//		return scanBackward(document, position, bound, new char[] {ch});
//	}
//
	/**
	 * Finds the lowest position in <code>document</code> such that the position is &gt;= <code>position</code>
	 * and &lt; <code>bound</code> and <code>document.getChar(position) == ch</code> evaluates to <code>true</code> for at least one
	 * ch in <code>chars</code> and the position is in the default partition.
	 *
	 * @param document the document being modified
	 * @param position the first character position in <code>document</code> to be considered
	 * @param partitioning the document partitioning
	 * @param bound the first position in <code>document</code> to not consider any more, with <code>scanTo</code> &gt; <code>position</code>
	 * @param chars an array of <code>char</code> to search for
	 * @return the lowest position of one element in <code>chars</code> in [<code>position</code>, <code>bound</code>) that resides in a Java partition, or <code>-1</code> if none can be found
	 */
	private static int scanForward(IDocument document, int position, String partitioning, int bound, char[] chars) {
		Assert.isTrue(position >= 0);
		Assert.isTrue(bound <= document.getLength());

		Arrays.sort(chars);

		try {
			while (position < bound) {

				if (Arrays.binarySearch(chars, document.getChar(position)) >= 0 && isDefaultPartition(document, position, partitioning))
					return position;

				position++;
			}
		} catch (BadLocationException e) {
		}
		return -1;
	}

	/**
	 * Finds the lowest position in <code>document</code> such that the position is &gt;= <code>position</code>
	 * and &lt; <code>bound</code> and <code>document.getChar(position) == ch</code> evaluates to <code>true</code>
	 * and the position is in the default partition.
	 *
	 * @param document the document being modified
	 * @param position the first character position in <code>document</code> to be considered
	 * @param partitioning the document partitioning
	 * @param bound the first position in <code>document</code> to not consider any more, with <code>scanTo</code> &gt; <code>position</code>
	 * @param ch a <code>char</code> to search for
	 * @return the lowest position of one element in <code>chars</code> in [<code>position</code>, <code>bound</code>) that resides in a Java partition, or <code>-1</code> if none can be found
	 */
	private static int scanForward(IDocument document, int position, String partitioning, int bound, char ch) {
		return scanForward(document, position, partitioning, bound, new char[] {ch});
	}

	/**
	 * Checks whether the content of <code>document</code> in the range (<code>offset</code>, <code>length</code>)
	 * contains the <code>new</code> keyword.
	 *
	 * @param document the document being modified
	 * @param offset the first character position in <code>document</code> to be considered
	 * @param length the length of the character range to be considered
	 * @param partitioning the document partitioning
	 * @return <code>true</code> if the specified character range contains a <code>new</code> keyword, <code>false</code> otherwise.
	 */
	private static boolean isNewMatch(IDocument document, int offset, int length, String partitioning) {
		Assert.isTrue(length >= 0);
		Assert.isTrue(offset >= 0);
		Assert.isTrue(offset + length < document.getLength() + 1);

		try {
			String text= document.get(offset, length);
			int pos= text.indexOf("new"); //$NON-NLS-1$

			while (pos != -1 && !isDefaultPartition(document, pos + offset, partitioning))
				pos= text.indexOf("new", pos + 2); //$NON-NLS-1$

			if (pos < 0)
				return false;

			if (pos != 0 && Character.isJavaIdentifierPart(text.charAt(pos - 1)))
				return false;

			if (pos + 3 < length && Character.isJavaIdentifierPart(text.charAt(pos + 3)))
				return false;

			return true;

		} catch (BadLocationException e) {
		}
		return false;
	}

	/**
	 * Checks whether the content of <code>document</code> at <code>position</code> looks like an
	 * anonymous class definition. <code>position</code> must be to the left of the opening
	 * parenthesis of the definition's parameter list.
	 *
	 * @param document the document being modified
	 * @param position the first character position in <code>document</code> to be considered
	 * @param partitioning the document partitioning
	 * @return <code>true</code> if the content of <code>document</code> looks like an anonymous class definition, <code>false</code> otherwise
	 */
	private static boolean looksLikeAnonymousClassDef(IDocument document, int position, String partitioning) {
		int previousCommaParenEqual= scanBackward(document, position - 1, partitioning, -1, new char[] {',', '(', '='});
		if (previousCommaParenEqual == -1 || position < previousCommaParenEqual + 5) // 2 for borders, 3 for "new"
			return false;

		if (isNewMatch(document, previousCommaParenEqual + 1, position - previousCommaParenEqual - 2, partitioning))
			return true;

		return false;
	}

	/**
	 * Checks whether <code>position</code> resides in a default (Java) partition of <code>document</code>.
	 *
	 * @param document the document being modified
	 * @param position the position to be checked
	 * @param partitioning the document partitioning
	 * @return <code>true</code> if <code>position</code> is in the default partition of <code>document</code>, <code>false</code> otherwise
	 */
	private static boolean isDefaultPartition(IDocument document, int position, String partitioning) {
		Assert.isTrue(position >= 0);
		Assert.isTrue(position <= document.getLength());

		try {
			// don't use getPartition2 since we're interested in the scanned character's partition
			ITypedRegion region= TextUtilities.getPartition(document, partitioning, position, false);
			return region.getType().equals(IDocument.DEFAULT_CONTENT_TYPE);

		} catch (BadLocationException e) {
		}

		return false;
	}

	/**
	 * Finds the position of the parenthesis matching the closing parenthesis at <code>position</code>.
	 *
	 * @param document the document being modified
	 * @param position the position in <code>document</code> of a closing parenthesis
	 * @param partitioning the document partitioning
	 * @return the position in <code>document</code> of the matching parenthesis, or -1 if none can be found
	 */
	private static int findOpeningParenMatch(IDocument document, int position, String partitioning) {
		final char CLOSING_PAREN= ')';
		final char OPENING_PAREN= '(';

		Assert.isTrue(position < document.getLength());
		Assert.isTrue(position >= 0);
		Assert.isTrue(isDefaultPartition(document, position, partitioning));

		try {

			Assert.isTrue(document.getChar(position) == CLOSING_PAREN);

			int depth= 1;
			while (true) {
				position= scanBackward(document, position - 1, partitioning, -1, new char[] {CLOSING_PAREN, OPENING_PAREN});
				if (position == -1)
					return -1;

				if (document.getChar(position) == CLOSING_PAREN)
					depth++;
				else
					depth--;

				if (depth == 0)
					return position;
			}

		} catch (BadLocationException e) {
			return -1;
		}
	}

	/**
	 * Checks whether, to the left of <code>position</code> and separated only by whitespace,
	 * <code>document</code> contains a keyword taking a parameter list and a block after it.
	 * These are: <code>if</code>, <code>while</code>, <code>catch</code>, <code>for</code>, <code>synchronized</code>, <code>switch</code>.
	 *
	 * @param document the document being modified
	 * @param position the first character position in <code>document</code> to be considered
	 * @param partitioning the document partitioning
	 * @return <code>true</code> if <code>document</code> contains any of the above keywords to the left of <code>position</code>, <code>false</code> otherwise
	 */
	private static boolean looksLikeIfWhileForCatch(IDocument document, int position, String partitioning) {
		position= firstNonWhitespaceBackward(document, position, partitioning, -1);
		if (position == -1)
			return false;

		return looksLike(document, position, "if") //$NON-NLS-1$
				|| looksLike(document, position, "while") //$NON-NLS-1$
				|| looksLike(document, position, "catch") //$NON-NLS-1$
				|| looksLike(document, position, "synchronized") //$NON-NLS-1$
				|| looksLike(document, position, "switch") //$NON-NLS-1$
				|| looksLike(document, position, "for"); //$NON-NLS-1$
	}

	/**
	 * Checks whether code>document</code> contains the <code>String</code> <code>like</code> such
	 * that its last character is at <code>position</code>. If <code>like</code> starts with a
	 * identifier part (as determined by {@link Character#isJavaIdentifierPart(char)}), it is also made
	 * sure that <code>like</code> is preceded by some non-identifier character or stands at the
	 * document start.
	 *
	 * @param document the document being modified
	 * @param position the first character position in <code>document</code> to be considered
	 * @param like the <code>String</code> to look for.
	 * @return <code>true</code> if  <code>document</code> contains <code>like</code> such that it ends at <code>position</code>, <code>false</code> otherwise
	 */
	private static boolean looksLike(IDocument document, int position, String like) {
		int length= like.length();
		if (position < length - 1)
			return false;

		try {
			if (!like.equals(document.get(position - length + 1, length)))
				return false;

			if (position >= length && Character.isJavaIdentifierPart(like.charAt(0)) && Character.isJavaIdentifierPart(document.getChar(position - length)))
				return false;

		} catch (BadLocationException e) {
			return false;
		}

		return true;
	}

	/**
	 * Checks whether the content of <code>document</code> at <code>position</code> looks like a
	 * method declaration header (i.e. only the return type and method name). <code>position</code>
	 * must be just left of the opening parenthesis of the parameter list.
	 *
	 * @param document the document being modified
	 * @param position the first character position in <code>document</code> to be considered
	 * @param partitioning the document partitioning
	 * @return <code>true</code> if the content of <code>document</code> looks like a method definition, <code>false</code> otherwise
	 */
	private static boolean looksLikeMethodDecl(IDocument document, int position, String partitioning) {

		// method name
		position= eatIdentToLeft(document, position, partitioning);
		if (position < 1)
			return false;

		position= eatBrackets(document, position - 1, partitioning);
		if (position < 1)
			return false;

		position= eatIdentToLeft(document, position - 1, partitioning);

		return position != -1;
	}

	/**
	 * From <code>position</code> to the left, eats any whitespace and then a pair of brackets
	 * as used to declare an array return type like <pre>String [ ]</pre>.
	 * The return value is either the position of the opening bracket or <code>position</code> if no
	 * pair of brackets can be parsed.
	 *
	 * @param document the document being modified
	 * @param position the first character position in <code>document</code> to be considered
	 * @param partitioning the document partitioning
	 * @return the smallest character position of bracket pair or <code>position</code>
	 */
	private static int eatBrackets(IDocument document, int position, String partitioning) {
		// accept array return type
		int pos= firstNonWhitespaceBackward(document, position, partitioning, -1);
		try {
			if (pos > 1 && document.getChar(pos) == ']') {
				pos= firstNonWhitespaceBackward(document, pos - 1, partitioning, -1);
				if (pos > 0 && document.getChar(pos) == '[')
					return pos;
			}
		} catch (BadLocationException e) {
			// won't happen
		}
		return position;
	}

	/**
	 * From <code>position</code> to the left, eats any whitespace and the first identifier, returning
	 * the position of the first identifier character (in normal read order).
	 * <p>When called on a document with content <code>" some string  "</code> and positionition 13, the
	 * return value will be 6 (the first letter in <code>string</code>).
	 * </p>
	 *
	 * @param document the document being modified
	 * @param position the first character position in <code>document</code> to be considered
	 * @param partitioning the document partitioning
	 * @return the smallest character position of an identifier or -1 if none can be found; always &lt;= <code>position</code>
	 */
	private static int eatIdentToLeft(IDocument document, int position, String partitioning) {
		if (position < 0)
			return -1;
		Assert.isTrue(position < document.getLength());

		int p= firstNonWhitespaceBackward(document, position, partitioning, -1);
		if (p == -1)
			return -1;

		try {
			while (p >= 0) {

				char ch= document.getChar(p);
				if (Character.isJavaIdentifierPart(ch)) {
					p--;
					continue;
				}

				// length must be > 0
				if (Character.isWhitespace(ch) && p != position)
					return p + 1;
				else
					return -1;

			}

			// start of document reached
			return 0;

		} catch (BadLocationException e) {
		}
		return -1;
	}

	/**
	 * Returns a position in the first java partition after the last non-empty and non-comment partition.
	 * There is no non-whitespace from the returned position to the end of the partition it is contained in.
	 *
	 * @param document the document being modified
	 * @param line the line under investigation
	 * @param offset the caret offset into <code>line</code>
	 * @param partitioning the document partitioning
	 * @return the position of the next Java partition, or the end of <code>line</code>
	 */
	private static int nextPartitionOrLineEnd(IDocument document, ITextSelection line, int offset, String partitioning) {
		// run relative to document
		final int docOffset= offset + line.getOffset();
		final int eol= line.getOffset() + line.getLength();
		int nextPartitionPos= eol; // init with line end
		int validPosition= docOffset;

		try {
			ITypedRegion partition= TextUtilities.getPartition(document, partitioning, nextPartitionPos, true);
			validPosition= getValidPositionForPartition(document, partition, eol);
			while (validPosition == -1) {
				nextPartitionPos= partition.getOffset() - 1;
				if (nextPartitionPos < docOffset) {
					validPosition= docOffset;
					break;
				}
				partition= TextUtilities.getPartition(document, partitioning, nextPartitionPos, false);
				validPosition= getValidPositionForPartition(document, partition, eol);
			}
		} catch (BadLocationException e) {
		}

		validPosition= Math.max(validPosition, docOffset);
		// make relative to line
		validPosition -= line.getOffset();
		return validPosition;
	}

	/**
	 * Returns a valid insert location (except for whitespace) in <code>partition</code> or -1 if
	 * there is no valid insert location.
	 * An valid insert location is right after any java string or character partition, or at the end
	 * of a java default partition, but never behind <code>maxOffset</code>. Comment partitions or
	 * empty java partitions do never yield valid insert positions.
	 *
	 * @param doc the document being modified
	 * @param partition the current partition
	 * @param maxOffset the maximum offset to consider
	 * @return a valid insert location in <code>partition</code>, or -1 if there is no valid insert location
	 */
	private static int getValidPositionForPartition(IDocument doc, ITypedRegion partition, int maxOffset) {
		final int INVALID= -1;

		if (IJavaPartitions.JAVA_DOC.equals(partition.getType()))
			return INVALID;
		if (IJavaPartitions.JAVA_MULTI_LINE_COMMENT.equals(partition.getType()))
			return INVALID;
		if (IJavaPartitions.JAVA_SINGLE_LINE_COMMENT.equals(partition.getType()))
			return INVALID;

		int endOffset= Math.min(maxOffset, partition.getOffset() + partition.getLength());

		if (IJavaPartitions.JAVA_CHARACTER.equals(partition.getType()))
			return endOffset;
		if (IJavaPartitions.JAVA_STRING.equals(partition.getType()))
			return endOffset;
		if (IDocument.DEFAULT_CONTENT_TYPE.equals(partition.getType())) {
			try {
				if (doc.get(partition.getOffset(), endOffset - partition.getOffset()).trim().length() == 0)
					return INVALID;
				else
					return endOffset;
			} catch (BadLocationException e) {
				return INVALID;
			}
		}
		// default: we don't know anything about the partition - assume valid
		return endOffset;
	}

	/**
	 * Determines whether the current line contains a for statement.
	 * Algorithm: any "for" word in the line is a positive, "for" contained in a string literal will
	 * produce a false positive.
	 *
	 * @param line the line where the change is being made
	 * @param offset the position of the caret
	 * @return <code>true</code> if <code>line</code> contains <code>for</code>, <code>false</code> otherwise
	 */
	private static boolean isForStatement(String line, int offset) {
		/* searching for (^|\s)for(\s|$) */
		int forPos= line.indexOf("for"); //$NON-NLS-1$
		if (forPos != -1) {
			if ((forPos == 0 || !Character.isJavaIdentifierPart(line.charAt(forPos - 1))) && (line.length() == forPos + 3 || !Character.isJavaIdentifierPart(line.charAt(forPos + 3))))
				return true;
		}
		return false;
	}

	/**
	 * Returns the position in <code>text</code> after which there comes only whitespace, up to
	 * <code>offset</code>.
	 *
	 * @param text the text being searched
	 * @param offset the maximum offset to search for
	 * @return the smallest value <code>v</code> such that <code>text.substring(v, offset).trim() == 0</code>
	 */
	private static int startOfWhitespaceBeforeOffset(String text, int offset) {
		int i= Math.min(offset, text.length());
		for (; i >= 1; i--) {
			if (!Character.isWhitespace(text.charAt(i - 1)))
				break;
		}
		return i;
	}
}
