X-Git-Url: http://secure.phpeclipse.com diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/SmartSemicolonAutoEditStrategy.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/SmartSemicolonAutoEditStrategy.java deleted file mode 100644 index edd3013..0000000 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/SmartSemicolonAutoEditStrategy.java +++ /dev/null @@ -1,1005 +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.core.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 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= PHPeclipsePlugin.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= PHPeclipsePlugin.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 && PHPeclipsePlugin.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) { - PHPeclipsePlugin.log(e); - } catch (BadLocationException e) { - PHPeclipsePlugin.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 (Character.isJavaIdentifierPart(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 && 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 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 Character#isJavaIdentifier(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 && 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 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 (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 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 (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 || !Character.isJavaIdentifierPart(line.charAt(forPos - 1))) && (line.length() == forPos + 3 || !Character.isJavaIdentifierPart(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; - } -}