X-Git-Url: http://secure.phpeclipse.com diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/SmartSemicolonAutoEditStrategy.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/SmartSemicolonAutoEditStrategy.java deleted file mode 100644 index f3e79b3..0000000 --- a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/SmartSemicolonAutoEditStrategy.java +++ /dev/null @@ -1,1301 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2000, 2004 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Common Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/cpl-v10.html - * - * Contributors: - * IBM Corporation - initial API and implementation - *******************************************************************************/ -package net.sourceforge.phpdt.internal.ui.text; - -import java.util.Arrays; - -import net.sourceforge.phpdt.internal.compiler.parser.Scanner; -//incastrix -//import net.sourceforge.phpdt.internal.corext.Assert; -import org.eclipse.core.runtime.Assert; -import net.sourceforge.phpdt.internal.ui.text.SmartBackspaceManager.UndoSpec; -import net.sourceforge.phpdt.ui.PreferenceConstants; -//import net.sourceforge.phpeclipse.PHPeclipsePlugin; -import net.sourceforge.phpeclipse.phpeditor.PHPUnitEditor; -import net.sourceforge.phpeclipse.ui.WebUI; - -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.text.edits.DeleteEdit; -import org.eclipse.text.edits.MalformedTreeException; -import org.eclipse.text.edits.ReplaceEdit; -import org.eclipse.text.edits.TextEdit; -import org.eclipse.ui.IEditorPart; -import org.eclipse.ui.IWorkbenchPage; -import org.eclipse.ui.texteditor.ITextEditorExtension2; -import org.eclipse.ui.texteditor.ITextEditorExtension3; - -/** - * Modifies DocumentCommands 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. - * - *

- * 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 - * for statements definition. If the line contains a semicolon or - * brace after the current caret position, the cursor is moved after it. - *

- * - * @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) - */ - public void customizeDocumentCommand(IDocument document, - DocumentCommand command) { - // 0: early pruning - // also customize if doit 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 = WebUI.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 = WebUI.getActivePage(); - if (page == null) - return; - IEditorPart part = page.getActiveEditor(); - if (!(part instanceof PHPUnitEditor)) - return; - PHPUnitEditor editor = (PHPUnitEditor) part; - if (editor.getInsertMode() != ITextEditorExtension3.SMART_INSERT - || !editor.isEditable()) - return; - ITextEditorExtension2 extension = (ITextEditorExtension2) 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 = (SmartBackspaceManager) editor - .getAdapter(SmartBackspaceManager.class); - if (manager != null - && WebUI.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 e) { - WebUI.log(e); - } catch (BadLocationException e) { - WebUI.log(e); - } - - } - - /** - * Returns true if the document command is applied on a multi - * line selection, false otherwise. - * - * @param document - * the document - * @param command - * the command - * @return true if command 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 try, else, do. - * - * @param document - * the document we are working on - * @param position - * the insert position of character - * @param character - * the character to be inserted - * @return a String consisting of character - * 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 - * position. - * - * @param document - * the document we are working on - * @param position - * the insert position of ch - * @param character - * the character to be inserted - * @return true if ch is already present at - * location, false 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 - * character was typed - * @param character - * the character to look for - * @param partitioning - * the document partitioning - * @return the position where character 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; - - int insertPos; - if (character == BRACECHAR) { - - insertPos = computeArrayInitializationPos(document, line, offset, - partitioning); - - if (insertPos == -1) { - insertPos = computeAfterTryDoElse(document, line, offset); - } - - if (insertPos == -1) { - insertPos = computeAfterParenthesis(document, line, offset, - partitioning); - } - - } else if (character == 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 { - Assert.isTrue(false); - return -1; - } - - return insertPos; - } - - /** - * Computes an insert position for an opening brace if offset - * maps to a position in document 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 - * line looks like being an array initialization at - * offset, -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 (Scanner.isPHPIdentifierPart(ch) || ch == ']' || ch == '[') - return offset; - - } catch (BadLocationException e) { - } - return -1; - } - - /** - * Computes an insert position for an opening brace if offset - * maps to a position in document involving a keyword taking - * a block after it. These are: try, do, - * synchronized, static, - * finally, or else. - * - * @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. - * @return an insert position relative to the line start if - * line contains one of the above keywords at or - * before offset, -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 offset - * maps to a position in document 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 - * line 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 position in - * document, where that parenthesis is only separated by whitespace from - * position. If no such parenthesis can be found, - * position is returned. - * - * @param document - * the document being modified - * @param position - * the first character position in document to be - * considered - * @param partitioning - * the document partitioning - * @return the position of a closing parenthesis left to - * position separated only by whitespace, or - * position 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) position. - * - * @param document - * the document being modified - * @param position - * the first character position in document to be - * considered - * @return the position of a whitespace character greater or equal than - * position 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 document such that the - * position is <= position and > bound - * and Character.isWhitespace(document.getChar(pos)) - * evaluates to false and the position is in the default - * partition. - * - * @param document - * the document being modified - * @param position - * the first character position in document to be - * considered - * @param partitioning - * the document partitioning - * @param bound - * the first position in document to not consider - * any more, with bound > position - * @return the highest position of one element in chars in [position, - * scanTo) that resides in a Java partition, or - * -1 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 document such that the - * position is >= position and < bound - * and Character.isWhitespace(document.getChar(pos)) - * evaluates to false and the position is in the default - * partition. - * - * @param document - * the document being modified - * @param position - * the first character position in document to be - * considered - * @param partitioning - * the document partitioning - * @param bound - * the first position in document to not consider - * any more, with bound > position - * @return the smallest position of one element in chars in [position, - * scanTo) that resides in a Java partition, or - * -1 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 document such that the - * position is <= position and > bound - * and document.getChar(position) == ch evaluates to - * true for at least one ch in chars and the - * position is in the default partition. - * - * @param document - * the document being modified - * @param position - * the first character position in document to be - * considered - * @param partitioning - * the document partitioning - * @param bound - * the first position in document to not consider - * any more, with scanTo > - * position - * @param chars - * an array of char to search for - * @return the highest position of one element in chars in (bound, - * position] that resides in a Java partition, or - * -1 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 document such that the - // position is <= position - // * and > bound and document.getChar(position) == - // ch evaluates to true - // * and the position is in the default partition. - // * - // * @param document the document being modified - // * @param position the first character position in document - // to be considered - // * @param bound the first position in document to not - // consider any more, with scanTo > position - // * @param chars an array of char to search for - // * @return the highest position of one element in chars in - // [position, scanTo) that resides in a Java - // partition, or -1 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 document such that the - * position is >= position and < bound - * and document.getChar(position) == ch evaluates to - * true for at least one ch in chars and the - * position is in the default partition. - * - * @param document - * the document being modified - * @param position - * the first character position in document to be - * considered - * @param partitioning - * the document partitioning - * @param bound - * the first position in document to not consider - * any more, with scanTo > - * position - * @param chars - * an array of char to search for - * @return the lowest position of one element in chars in [position, - * bound) that resides in a Java partition, or - * -1 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 document such that the - * position is >= position and < bound - * and document.getChar(position) == ch evaluates to - * true and the position is in the default partition. - * - * @param document - * the document being modified - * @param position - * the first character position in document to be - * considered - * @param partitioning - * the document partitioning - * @param bound - * the first position in document to not consider - * any more, with scanTo > - * position - * @param chars - * an array of char to search for - * @return the lowest position of one element in chars in [position, - * bound) that resides in a Java partition, or - * -1 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 document in the range (offset, - * length) contains the new keyword. - * - * @param document - * the document being modified - * @param offset - * the first character position in document to be - * considered - * @param length - * the length of the character range to be considered - * @param partitioning - * the document partitioning - * @return true if the specified character range contains a - * new keyword, false 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 && Scanner.isPHPIdentifierPart(text.charAt(pos - 1))) - return false; - - if (pos + 3 < length - && Scanner.isPHPIdentifierPart(text.charAt(pos + 3))) - return false; - - return true; - - } catch (BadLocationException e) { - } - return false; - } - - /** - * Checks whether the content of document at - * position looks like an anonymous class definition. - * position 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 document to be - * considered - * @param partitioning - * the document partitioning - * @return true if the content of document - * looks like an anonymous class definition, false - * otherwise - */ - private static boolean looksLikeAnonymousClassDef(IDocument document, - int position, String partitioning) { - int previousCommaOrParen = scanBackward(document, position - 1, - partitioning, -1, new char[] { ',', '(' }); - if (previousCommaOrParen == -1 || position < previousCommaOrParen + 5) // 2 - // for - // borders, - // 3 - // for - // "new" - return false; - - if (isNewMatch(document, previousCommaOrParen + 1, position - - previousCommaOrParen - 2, partitioning)) - return true; - - return false; - } - - /** - * Checks whether position resides in a default (Java) - * partition of document. - * - * @param document - * the document being modified - * @param position - * the position to be checked - * @param partitioning - * the document partitioning - * @return true if position is in the default - * partition of document, false - * 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 - * position. - * - * @param document - * the document being modified - * @param position - * the position in document of a closing - * parenthesis - * @param partitioning - * the document partitioning - * @return the position in document 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 position and separated only - * by whitespace, document contains a keyword taking a - * parameter list and a block after it. These are: if, - * while, catch, for, - * synchronized, switch. - * - * @param document - * the document being modified - * @param position - * the first character position in document to be - * considered - * @param partitioning - * the document partitioning - * @return true if document contains any of - * the above keywords to the left of position, - * false 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 contains the String like - * such that its last character is at position. If like - * starts with a identifier part (as determined by - * {@link Scanner#isPHPIdentifierPart(char)}), it is also made sure that - * like 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 document to be - * considered - * @param like - * the String to look for. - * @return true if document contains like - * such that it ends at position, false - * 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 - && Scanner.isPHPIdentifierPart(like.charAt(0)) - && Scanner.isPHPIdentifierPart(document.getChar(position - - length))) - return false; - - } catch (BadLocationException e) { - return false; - } - - return true; - } - - /** - * Checks whether the content of document at - * position looks like a method declaration header (i.e. only - * the return type and method name). position 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 document to be - * considered - * @param partitioning - * the document partitioning - * @return true if the content of document - * looks like a method definition, false 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 position to the left, eats any whitespace and then a - * pair of brackets as used to declare an array return type like - * - *
-	 * String [ ]
-	 * 
. The return value is either the position of the opening bracket - * or position if no pair of brackets can be parsed. - * - * @param document - * the document being modified - * @param position - * the first character position in document to be - * considered - * @param partitioning - * the document partitioning - * @return the smallest character position of bracket pair or - * position - */ - 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 position to the left, eats any whitespace and the - * first identifier, returning the position of the first identifier - * character (in normal read order). - *

- * When called on a document with content " some string " and - * positionition 13, the return value will be 6 (the first letter in - * string). - *

- * - * @param document - * the document being modified - * @param position - * the first character position in document to be - * considered - * @param partitioning - * the document partitioning - * @return the smallest character position of an identifier or -1 if none - * can be found; always <= position - */ - 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 (Scanner.isPHPIdentifierPart(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 line - * @param partitioning - * the document partitioning - * @return the position of the next Java partition, or the end of - * line - */ - 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 - * partition 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 - * maxOffset. 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 partition, or -1 if - * there is no valid insert location - */ - private static int getValidPositionForPartition(IDocument doc, - ITypedRegion partition, int maxOffset) { - final int INVALID = -1; - - if (IPHPPartitions.PHP_PHPDOC_COMMENT.equals(partition.getType())) - return INVALID; - if (IPHPPartitions.PHP_MULTILINE_COMMENT.equals(partition.getType())) - return INVALID; - if (IPHPPartitions.PHP_SINGLELINE_COMMENT.equals(partition.getType())) - return INVALID; - - int endOffset = Math.min(maxOffset, partition.getOffset() - + partition.getLength()); - - // if (IPHPPartitions.JAVA_CHARACTER.equals(partition.getType())) - // return endOffset; - if (IPHPPartitions.PHP_STRING_DQ.equals(partition.getType())) - return endOffset; - if (IPHPPartitions.PHP_STRING_SQ.equals(partition.getType())) - return endOffset; - if (IPHPPartitions.PHP_STRING_HEREDOC.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 true if line contains - * for, false 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 || !Scanner.isPHPIdentifierPart(line - .charAt(forPos - 1))) - && (line.length() == forPos + 3 || !Scanner - .isPHPIdentifierPart(line.charAt(forPos + 3)))) - return true; - } - return false; - } - - /** - * Returns the position in text after which there comes only - * whitespace, up to offset. - * - * @param text - * the text being searched - * @param offset - * the maximum offset to search for - * @return the smallest value v such that - * text.substring(v, offset).trim() == 0 - */ - 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; - } -}