X-Git-Url: http://secure.phpeclipse.com diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/JavaHeuristicScanner.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/JavaHeuristicScanner.java index d7ef909..0ca33ab 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/JavaHeuristicScanner.java +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/JavaHeuristicScanner.java @@ -13,6 +13,7 @@ package net.sourceforge.phpdt.internal.ui.text; import java.util.Arrays; import net.sourceforge.phpdt.internal.compiler.parser.Scanner; +import net.sourceforge.phpeclipse.phpeditor.php.PHPDocumentPartitioner; import org.eclipse.jface.text.Assert; import org.eclipse.jface.text.BadLocationException; @@ -23,57 +24,75 @@ import org.eclipse.jface.text.Region; import org.eclipse.jface.text.TextUtilities; /** - * Utility methods for heuristic based Java manipulations in an incomplete Java source file. + * Utility methods for heuristic based Java manipulations in an incomplete Java + * source file. * - *

An instance holds some internal position in the document and is therefore not threadsafe.

+ *

+ * An instance holds some internal position in the document and is therefore not + * threadsafe. + *

* * @since 3.0 */ public class JavaHeuristicScanner implements Symbols { - /** - * Returned by all methods when the requested position could not be found, or if a - * {@link BadLocationException} was thrown while scanning. + /** + * Returned by all methods when the requested position could not be found, + * or if a {@link BadLocationException} was thrown while scanning. */ - public static final int NOT_FOUND= -1; + public static final int NOT_FOUND = -1; - /** - * Special bound parameter that means either -1 (backward scanning) or + /** + * Special bound parameter that means either -1 (backward scanning) or * fDocument.getLength() (forward scanning). */ - public static final int UNBOUND= -2; - + public static final int UNBOUND = -2; /* character constants */ - private static final char LBRACE= '{'; - private static final char RBRACE= '}'; - private static final char LPAREN= '('; - private static final char RPAREN= ')'; - private static final char SEMICOLON= ';'; - private static final char COLON= ':'; - private static final char COMMA= ','; - private static final char LBRACKET= '['; - private static final char RBRACKET= ']'; - private static final char QUESTIONMARK= '?'; - private static final char EQUAL= '='; + private static final char LBRACE = '{'; + + private static final char RBRACE = '}'; + + private static final char LPAREN = '('; + + private static final char RPAREN = ')'; + + private static final char SEMICOLON = ';'; + + private static final char COLON = ':'; + + private static final char COMMA = ','; + + private static final char LBRACKET = '['; + + private static final char RBRACKET = ']'; + + private static final char QUESTIONMARK = '?'; + + private static final char EQUAL = '='; /** - * Specifies the stop condition, upon which the scanXXX methods will decide whether - * to keep scanning or not. This interface may implemented by clients. + * Specifies the stop condition, upon which the scanXXX + * methods will decide whether to keep scanning or not. This interface may + * implemented by clients. */ public interface StopCondition { /** * Instructs the scanner to return the current position. * - * @param ch the char at the current position - * @param position the current position - * @param forward the iteration direction + * @param ch + * the char at the current position + * @param position + * the current position + * @param forward + * the iteration direction * @return true if the stop condition is met. */ boolean stop(char ch, int position, boolean forward); } - + /** - * Stops upon a non-whitespace (as defined by {@link Character#isWhitespace(char)}) character. + * Stops upon a non-whitespace (as defined by + * {@link Character#isWhitespace(char)}) character. */ private static class NonWhitespace implements StopCondition { /* @@ -83,23 +102,25 @@ public class JavaHeuristicScanner implements Symbols { return !Character.isWhitespace(ch); } } - + /** * Stops upon a non-whitespace character in the default partition. * - * @see NonWhitespace + * @see NonWhitespace */ private class NonWhitespaceDefaultPartition extends NonWhitespace { /* * @see net.sourceforge.phpdt.internal.ui.text.JavaHeuristicScanner.StopCondition#stop(char) */ public boolean stop(char ch, int position, boolean forward) { - return super.stop(ch, position, true) && isDefaultPartition(position); + return super.stop(ch, position, true) + && isDefaultPartition(position); } } - + /** - * Stops upon a non-java identifier (as defined by {@link Scanner#isPHPIdentifierPart(char)}) character. + * Stops upon a non-java identifier (as defined by + * {@link Scanner#isPHPIdentifierPart(char)}) character. */ private static class NonJavaIdentifierPart implements StopCondition { /* @@ -109,83 +130,98 @@ public class JavaHeuristicScanner implements Symbols { return !Scanner.isPHPIdentifierPart(ch); } } - + /** * Stops upon a non-java identifier character in the default partition. * - * @see NonJavaIdentifierPart + * @see NonJavaIdentifierPart */ - private class NonJavaIdentifierPartDefaultPartition extends NonJavaIdentifierPart { + private class NonJavaIdentifierPartDefaultPartition extends + NonJavaIdentifierPart { /* * @see net.sourceforge.phpdt.internal.ui.text.JavaHeuristicScanner.StopCondition#stop(char) */ public boolean stop(char ch, int position, boolean forward) { - return super.stop(ch, position, true) || !isDefaultPartition(position); + return super.stop(ch, position, true) + || !isDefaultPartition(position); } } - + /** - * Stops upon a character in the default partition that matches the given character list. + * Stops upon a character in the default partition that matches the given + * character list. */ private class CharacterMatch implements StopCondition { private final char[] fChars; - + /** * Creates a new instance. - * @param ch the single character to match + * + * @param ch + * the single character to match */ public CharacterMatch(char ch) { - this(new char[] {ch}); + this(new char[] { ch }); } - + /** * Creates a new instance. - * @param chars the chars to match. + * + * @param chars + * the chars to match. */ public CharacterMatch(char[] chars) { Assert.isNotNull(chars); Assert.isTrue(chars.length > 0); - fChars= chars; + fChars = chars; Arrays.sort(chars); } - + /* - * @see net.sourceforge.phpdt.internal.ui.text.JavaHeuristicScanner.StopCondition#stop(char, int) + * @see net.sourceforge.phpdt.internal.ui.text.JavaHeuristicScanner.StopCondition#stop(char, + * int) */ public boolean stop(char ch, int position, boolean forward) { - return Arrays.binarySearch(fChars, ch) >= 0 && isDefaultPartition(position); + return Arrays.binarySearch(fChars, ch) >= 0 + && isDefaultPartition(position); } } - + /** - * Acts like character match, but skips all scopes introduced by parenthesis, brackets, and - * braces. + * Acts like character match, but skips all scopes introduced by + * parenthesis, brackets, and braces. */ protected class SkippingScopeMatch extends CharacterMatch { private char fOpening, fClosing; - private int fDepth= 0; - + + private int fDepth = 0; + /** * Creates a new instance. - * @param ch the single character to match + * + * @param ch + * the single character to match */ public SkippingScopeMatch(char ch) { super(ch); } - + /** * Creates a new instance. - * @param chars the chars to match. + * + * @param chars + * the chars to match. */ public SkippingScopeMatch(char[] chars) { super(chars); } /* - * @see net.sourceforge.phpdt.internal.ui.text.JavaHeuristicScanner.StopCondition#stop(char, int) + * @see net.sourceforge.phpdt.internal.ui.text.JavaHeuristicScanner.StopCondition#stop(char, + * int) */ public boolean stop(char ch, int position, boolean forward) { - + if (fDepth == 0 && super.stop(ch, position, true)) return true; else if (ch == fOpening) @@ -193,97 +229,111 @@ public class JavaHeuristicScanner implements Symbols { else if (ch == fClosing) { fDepth--; if (fDepth == 0) { - fOpening= 0; - fClosing= 0; + fOpening = 0; + fClosing = 0; } } else if (fDepth == 0) { - fDepth= 1; + fDepth = 1; if (forward) { - + switch (ch) { - case LBRACE: - fOpening= LBRACE; - fClosing= RBRACE; - break; - case LPAREN: - fOpening= LPAREN; - fClosing= RPAREN; - break; - case LBRACKET: - fOpening= LBRACKET; - fClosing= RBRACKET; - break; + case LBRACE: + fOpening = LBRACE; + fClosing = RBRACE; + break; + case LPAREN: + fOpening = LPAREN; + fClosing = RPAREN; + break; + case LBRACKET: + fOpening = LBRACKET; + fClosing = RBRACKET; + break; } - + } else { switch (ch) { - case RBRACE: - fOpening= RBRACE; - fClosing= LBRACE; - break; - case RPAREN: - fOpening= RPAREN; - fClosing= LPAREN; - break; - case RBRACKET: - fOpening= RBRACKET; - fClosing= LBRACKET; - break; + case RBRACE: + fOpening = RBRACE; + fClosing = LBRACE; + break; + case RPAREN: + fOpening = RPAREN; + fClosing = LPAREN; + break; + case RBRACKET: + fOpening = RBRACKET; + fClosing = LBRACKET; + break; } - + } } - + return false; - + } } - + /** The document being scanned. */ private IDocument fDocument; + /** The partitioning being used for scanning. */ private String fPartitioning; + /** The partition to scan in. */ private String fPartition; - /* internal scan state */ - + /* internal scan state */ + /** the most recently read character. */ private char fChar; + /** the most recently read position. */ private int fPos; - + /* preset stop conditions */ - private final StopCondition fNonWSDefaultPart= new NonWhitespaceDefaultPartition(); - private final static StopCondition fNonWS= new NonWhitespace(); - private final StopCondition fNonIdent= new NonJavaIdentifierPartDefaultPartition(); + private final StopCondition fNonWSDefaultPart = new NonWhitespaceDefaultPartition(); + + private final static StopCondition fNonWS = new NonWhitespace(); + + private final StopCondition fNonIdent = new NonJavaIdentifierPartDefaultPartition(); /** * Creates a new instance. * - * @param document the document to scan - * @param partitioning the partitioning to use for scanning - * @param partition the partition to scan in + * @param document + * the document to scan + * @param partitioning + * the partitioning to use for scanning + * @param partition + * the partition to scan in */ - public JavaHeuristicScanner(IDocument document, String partitioning, String partition) { + public JavaHeuristicScanner(IDocument document, String partitioning, + String partition) { Assert.isNotNull(document); Assert.isNotNull(partitioning); Assert.isNotNull(partition); - fDocument= document; - fPartitioning= partitioning; - fPartition= partition; + fDocument = document; + fPartitioning = partitioning; + fPartition = partition; } - + /** - * Calls this(document, IJavaPartitions.JAVA_PARTITIONING, IDocument.DEFAULT_CONTENT_TYPE). + * Calls + * this(document, IJavaPartitions.JAVA_PARTITIONING, IDocument.DEFAULT_CONTENT_TYPE). * - * @param document the document to scan. + * @param document + * the document to scan. */ public JavaHeuristicScanner(IDocument document) { - this(document, IPHPPartitions.PHP_PARTITIONING, IDocument.DEFAULT_CONTENT_TYPE); +// this(document, IPHPPartitions.PHP_PARTITIONING, +// IDocument.DEFAULT_CONTENT_TYPE); + this(document, IPHPPartitions.PHP_PARTITIONING, + PHPDocumentPartitioner.PHP_SCRIPT_CODE); } - + /** * Returns the most recent internal scan position. * @@ -292,233 +342,277 @@ public class JavaHeuristicScanner implements Symbols { public int getPosition() { return fPos; } - + /** - * Returns the next token in forward direction, starting at start, and not extending - * further than bound. The return value is one of the constants defined in {@link Symbols}. - * After a call, {@link #getPosition()} will return the position just after the scanned token - * (i.e. the next position that will be scanned). + * Returns the next token in forward direction, starting at + * start, and not extending further than bound. + * The return value is one of the constants defined in {@link Symbols}. + * After a call, {@link #getPosition()} will return the position just after + * the scanned token (i.e. the next position that will be scanned). * - * @param start the first character position in the document to consider - * @param bound the first position not to consider any more + * @param start + * the first character position in the document to consider + * @param bound + * the first position not to consider any more * @return a constant from {@link Symbols} describing the next token */ public int nextToken(int start, int bound) { - int pos= scanForward(start, bound, fNonWSDefaultPart); + int pos = scanForward(start, bound, fNonWSDefaultPart); if (pos == NOT_FOUND) return TokenEOF; fPos++; - + switch (fChar) { - case LBRACE: - return TokenLBRACE; - case RBRACE: - return TokenRBRACE; - case LBRACKET: - return TokenLBRACKET; - case RBRACKET: - return TokenRBRACKET; - case LPAREN: - return TokenLPAREN; - case RPAREN: - return TokenRPAREN; - case SEMICOLON: - return TokenSEMICOLON; - case COMMA: - return TokenCOMMA; - case QUESTIONMARK: - return TokenQUESTIONMARK; - case EQUAL: - return TokenEQUAL; + case LBRACE: + return TokenLBRACE; + case RBRACE: + return TokenRBRACE; + case LBRACKET: + return TokenLBRACKET; + case RBRACKET: + return TokenRBRACKET; + case LPAREN: + return TokenLPAREN; + case RPAREN: + return TokenRPAREN; + case SEMICOLON: + return TokenSEMICOLON; + case COMMA: + return TokenCOMMA; + case QUESTIONMARK: + return TokenQUESTIONMARK; + case EQUAL: + try { + if (fDocument.getChar(fPos) == '>') { + fPos++; + return TokenOTHER; + } + } catch (BadLocationException e) { + } + return TokenEQUAL; + case '<': + try { + if (fDocument.get(fPos, 4).equalsIgnoreCase("?php")) { + fPos += 4; + return TokenEOF; + } else if (fDocument.getChar(fPos) == '?') { + fPos++; + return TokenEOF; + } + } catch (BadLocationException e) { + } } - + // else if (Scanner.isPHPIdentifierPart(fChar)) { // assume an ident or keyword - int from= pos, to; - pos= scanForward(pos + 1, bound, fNonIdent); + int from = pos, to; + pos = scanForward(pos + 1, bound, fNonIdent); if (pos == NOT_FOUND) - to= bound == UNBOUND ? fDocument.getLength() : bound; + to = bound == UNBOUND ? fDocument.getLength() : bound; else - to= pos; - + to = pos; + String identOrKeyword; try { - identOrKeyword= fDocument.get(from, to - from); + identOrKeyword = fDocument.get(from, to - from); } catch (BadLocationException e) { return TokenEOF; } - + return getToken(identOrKeyword); - - + } else { // operators, number literals etc return TokenOTHER; } } - + /** - * Returns the next token in backward direction, starting at start, and not extending - * further than bound. The return value is one of the constants defined in {@link Symbols}. - * After a call, {@link #getPosition()} will return the position just before the scanned token - * starts (i.e. the next position that will be scanned). + * Returns the next token in backward direction, starting at + * start, and not extending further than bound. + * The return value is one of the constants defined in {@link Symbols}. + * After a call, {@link #getPosition()} will return the position just before + * the scanned token starts (i.e. the next position that will be scanned). * - * @param start the first character position in the document to consider - * @param bound the first position not to consider any more + * @param start + * the first character position in the document to consider + * @param bound + * the first position not to consider any more * @return a constant from {@link Symbols} describing the previous token */ public int previousToken(int start, int bound) { - int pos= scanBackward(start, bound, fNonWSDefaultPart); + int pos = scanBackward(start, bound, fNonWSDefaultPart); if (pos == NOT_FOUND) return TokenEOF; - + fPos--; - + switch (fChar) { - case LBRACE: - return TokenLBRACE; - case RBRACE: - return TokenRBRACE; - case LBRACKET: - return TokenLBRACKET; - case RBRACKET: - return TokenRBRACKET; - case LPAREN: - return TokenLPAREN; - case RPAREN: - return TokenRPAREN; - case SEMICOLON: - return TokenSEMICOLON; - case COLON: - return TokenCOLON; - case COMMA: - return TokenCOMMA; - case QUESTIONMARK: - return TokenQUESTIONMARK; - case EQUAL: - return TokenEQUAL; + case LBRACE: + return TokenLBRACE; + case RBRACE: + return TokenRBRACE; + case LBRACKET: + return TokenLBRACKET; + case RBRACKET: + return TokenRBRACKET; + case LPAREN: + return TokenLPAREN; + case RPAREN: + return TokenRPAREN; + case SEMICOLON: + return TokenSEMICOLON; + case COLON: + return TokenCOLON; + case COMMA: + return TokenCOMMA; + case QUESTIONMARK: + return TokenQUESTIONMARK; + case EQUAL: + return TokenEQUAL; + case '>': + try { + switch (fDocument.getChar(fPos)) { + case '=': + fPos--; + return TokenOTHER; + case '?': + fPos--; + return TokenEOF; + } + } catch (BadLocationException e) { + } } - + // else if (Scanner.isPHPIdentifierPart(fChar)) { // assume an ident or keyword - int from, to= pos + 1; - pos= scanBackward(pos - 1, bound, fNonIdent); + int from, to = pos + 1; + pos = scanBackward(pos - 1, bound, fNonIdent); if (pos == NOT_FOUND) - from= bound == UNBOUND ? 0 : bound + 1; + from = bound == UNBOUND ? 0 : bound + 1; else - from= pos + 1; - + from = pos + 1; + String identOrKeyword; try { - identOrKeyword= fDocument.get(from, to - from); + identOrKeyword = fDocument.get(from, to - from); } catch (BadLocationException e) { return TokenEOF; } - + return getToken(identOrKeyword); - - + } else { // operators, number literals etc return TokenOTHER; } - + } /** - * Returns one of the keyword constants or TokenIDENT for a scanned identifier. + * Returns one of the keyword constants or TokenIDENT for a + * scanned identifier. * - * @param s a scanned identifier + * @param s + * a scanned identifier * @return one of the constants defined in {@link Symbols} */ private int getToken(String s) { Assert.isNotNull(s); - + switch (s.length()) { - case 2: - if ("if".equals(s)) //$NON-NLS-1$ - return TokenIF; - if ("do".equals(s)) //$NON-NLS-1$ - return TokenDO; - break; - case 3: - if ("for".equals(s)) //$NON-NLS-1$ - return TokenFOR; - if ("try".equals(s)) //$NON-NLS-1$ - return TokenTRY; - if ("new".equals(s)) //$NON-NLS-1$ - return TokenNEW; - break; - case 4: - if ("case".equals(s)) //$NON-NLS-1$ - return TokenCASE; - if ("else".equals(s)) //$NON-NLS-1$ - return TokenELSE; - if ("goto".equals(s)) //$NON-NLS-1$ - return TokenGOTO; - break; - case 5: - if ("break".equals(s)) //$NON-NLS-1$ - return TokenBREAK; - if ("catch".equals(s)) //$NON-NLS-1$ - return TokenCATCH; - if ("while".equals(s)) //$NON-NLS-1$ - return TokenWHILE; - break; - case 6: - if ("return".equals(s)) //$NON-NLS-1$ - return TokenRETURN; - if ("static".equals(s)) //$NON-NLS-1$ - return TokenSTATIC; - if ("switch".equals(s)) //$NON-NLS-1$ - return TokenSWITCH; - break; - case 7: - if ("default".equals(s)) //$NON-NLS-1$ - return TokenDEFAULT; - if ("finally".equals(s)) //$NON-NLS-1$ - return TokenFINALLY; - break; - case 12: - if ("synchronized".equals(s)) //$NON-NLS-1$ - return TokenSYNCHRONIZED; - break; + case 2: + if ("if".equals(s)) //$NON-NLS-1$ + return TokenIF; + if ("do".equals(s)) //$NON-NLS-1$ + return TokenDO; + break; + case 3: + if ("for".equals(s)) //$NON-NLS-1$ + return TokenFOR; + if ("try".equals(s)) //$NON-NLS-1$ + return TokenTRY; + if ("new".equals(s)) //$NON-NLS-1$ + return TokenNEW; + break; + case 4: + if ("case".equals(s)) //$NON-NLS-1$ + return TokenCASE; + if ("else".equals(s)) //$NON-NLS-1$ + return TokenELSE; + if ("goto".equals(s)) //$NON-NLS-1$ + return TokenGOTO; + break; + case 5: + if ("break".equals(s)) //$NON-NLS-1$ + return TokenBREAK; + if ("catch".equals(s)) //$NON-NLS-1$ + return TokenCATCH; + if ("while".equals(s)) //$NON-NLS-1$ + return TokenWHILE; + break; + case 6: + if ("return".equals(s)) //$NON-NLS-1$ + return TokenRETURN; + if ("static".equals(s)) //$NON-NLS-1$ + return TokenSTATIC; + if ("switch".equals(s)) //$NON-NLS-1$ + return TokenSWITCH; + break; + case 7: + if ("default".equals(s)) //$NON-NLS-1$ + return TokenDEFAULT; + if ("finally".equals(s)) //$NON-NLS-1$ + return TokenFINALLY; + break; + case 12: + if ("synchronized".equals(s)) //$NON-NLS-1$ + return TokenSYNCHRONIZED; + break; } return TokenIDENT; } /** - * Returns the position of the closing peer character (forward search). Any scopes introduced by opening peers - * are skipped. All peers accounted for must reside in the default partition. + * Returns the position of the closing peer character (forward search). Any + * scopes introduced by opening peers are skipped. All peers accounted for + * must reside in the default partition. * - *

Note that start must not point to the opening peer, but to the first - * character being searched.

+ *

+ * Note that start must not point to the opening peer, but to + * the first character being searched. + *

* - * @param start the start position - * @param openingPeer the opening peer character (e.g. '{') - * @param closingPeer the closing peer character (e.g. '}') + * @param start + * the start position + * @param openingPeer + * the opening peer character (e.g. '{') + * @param closingPeer + * the closing peer character (e.g. '}') * @return the matching peer character position, or NOT_FOUND */ - public int findClosingPeer(int start, final char openingPeer, final char closingPeer) { + public int findClosingPeer(int start, final char openingPeer, + final char closingPeer) { Assert.isNotNull(fDocument); Assert.isTrue(start >= 0); - + try { - int depth= 1; + int depth = 1; start -= 1; while (true) { - start= scanForward(start + 1, UNBOUND, new CharacterMatch(new char[] {openingPeer, closingPeer})); + start = scanForward(start + 1, UNBOUND, new CharacterMatch( + new char[] { openingPeer, closingPeer })); if (start == NOT_FOUND) return NOT_FOUND; - + if (fDocument.getChar(start) == openingPeer) depth++; else depth--; - + if (depth == 0) return start; } @@ -529,33 +623,40 @@ public class JavaHeuristicScanner implements Symbols { } /** - * Returns the position of the opening peer character (backward search). Any scopes introduced by closing peers - * are skipped. All peers accounted for must reside in the default partition. + * Returns the position of the opening peer character (backward search). Any + * scopes introduced by closing peers are skipped. All peers accounted for + * must reside in the default partition. * - *

Note that start must not point to the closing peer, but to the first - * character being searched.

+ *

+ * Note that start must not point to the closing peer, but to + * the first character being searched. + *

* - * @param start the start position - * @param openingPeer the opening peer character (e.g. '{') - * @param closingPeer the closing peer character (e.g. '}') + * @param start + * the start position + * @param openingPeer + * the opening peer character (e.g. '{') + * @param closingPeer + * the closing peer character (e.g. '}') * @return the matching peer character position, or NOT_FOUND */ public int findOpeningPeer(int start, char openingPeer, char closingPeer) { Assert.isTrue(start < fDocument.getLength()); try { - int depth= 1; + int depth = 1; start += 1; while (true) { - start= scanBackward(start - 1, UNBOUND, new CharacterMatch(new char[] {openingPeer, closingPeer})); + start = scanBackward(start - 1, UNBOUND, new CharacterMatch( + new char[] { openingPeer, closingPeer })); if (start == NOT_FOUND) return NOT_FOUND; - + if (fDocument.getChar(start) == closingPeer) depth++; else depth--; - + if (depth == 0) return start; } @@ -566,84 +667,133 @@ public class JavaHeuristicScanner implements Symbols { } /** - * Computes the surrounding block around offset. The search is started at the - * beginning of offset, i.e. an opening brace at offset will not be - * part of the surrounding block, but a closing brace will. + * Computes the surrounding block around offset. The search + * is started at the beginning of offset, i.e. an opening + * brace at offset will not be part of the surrounding block, + * but a closing brace will. * - * @param offset the offset for which the surrounding block is computed - * @return a region describing the surrounding block, or null if none can be found + * @param offset + * the offset for which the surrounding block is computed + * @return a region describing the surrounding block, or null + * if none can be found */ public IRegion findSurroundingBlock(int offset) { if (offset < 1 || offset >= fDocument.getLength()) return null; - - int begin= findOpeningPeer(offset - 1, LBRACE, RBRACE); - int end= findClosingPeer(offset, LBRACE, RBRACE); + + int begin = findOpeningPeer(offset - 1, LBRACE, RBRACE); + int end = findClosingPeer(offset, LBRACE, RBRACE); if (begin == NOT_FOUND || end == NOT_FOUND) return null; return new Region(begin, end + 1 - begin); } /** - * Finds the smallest position in fDocument such that the position is >= position - * and < bound and Character.isWhitespace(fDocument.getChar(pos)) evaluates to false - * and the position is in the default partition. + * Finds the smallest position in fDocument such that the + * position is >= position and < bound + * and Character.isWhitespace(fDocument.getChar(pos)) + * evaluates to false and the position is in the default + * partition. * - * @param position the first character position in fDocument to be considered - * @param bound the first position in fDocument to not consider any more, with bound > position, or UNBOUND - * @return the smallest position of a non-whitespace character in [position, bound) that resides in a Java partition, or NOT_FOUND if none can be found + * @param position + * the first character position in fDocument to be + * considered + * @param bound + * the first position in fDocument to not consider + * any more, with bound > position, + * or UNBOUND + * @return the smallest position of a non-whitespace character in [position, + * bound) that resides in a Java partition, or + * NOT_FOUND if none can be found */ public int findNonWhitespaceForward(int position, int bound) { return scanForward(position, bound, fNonWSDefaultPart); } /** - * Finds the smallest position in fDocument such that the position is >= position - * and < bound and Character.isWhitespace(fDocument.getChar(pos)) evaluates to false. + * Finds the smallest position in fDocument such that the + * position is >= position and < bound + * and Character.isWhitespace(fDocument.getChar(pos)) + * evaluates to false. * - * @param position the first character position in fDocument to be considered - * @param bound the first position in fDocument to not consider any more, with bound > position, or UNBOUND - * @return the smallest position of a non-whitespace character in [position, bound), or NOT_FOUND if none can be found + * @param position + * the first character position in fDocument to be + * considered + * @param bound + * the first position in fDocument to not consider + * any more, with bound > position, + * or UNBOUND + * @return the smallest position of a non-whitespace character in [position, + * bound), or NOT_FOUND if none can + * be found */ public int findNonWhitespaceForwardInAnyPartition(int position, int bound) { return scanForward(position, bound, fNonWS); } /** - * Finds the highest position in fDocument such that the position is <= position - * and > bound and Character.isWhitespace(fDocument.getChar(pos)) evaluates to false - * and the position is in the default partition. + * Finds the highest position in fDocument such that the + * position is <= position and > bound + * and Character.isWhitespace(fDocument.getChar(pos)) + * evaluates to false and the position is in the default + * partition. * - * @param position the first character position in fDocument to be considered - * @param bound the first position in fDocument to not consider any more, with bound < position, or UNBOUND - * @return the highest position of a non-whitespace character in (bound, position] that resides in a Java partition, or NOT_FOUND if none can be found + * @param position + * the first character position in fDocument to be + * considered + * @param bound + * the first position in fDocument to not consider + * any more, with bound < position, + * or UNBOUND + * @return the highest position of a non-whitespace character in (bound, + * position] that resides in a Java partition, or + * NOT_FOUND if none can be found */ - public int findNonWhitespaceBackward(int position, int bound) { + public int findNonWhitespaceBackward(int position, int bound) { return scanBackward(position, bound, fNonWSDefaultPart); } /** - * Finds the lowest position p in fDocument such that start <= p < - * bound and condition.stop(fDocument.getChar(p), p) evaluates to true. + * Finds the lowest position p in fDocument + * such that start <= p < bound and + * condition.stop(fDocument.getChar(p), p) evaluates to + * true. * - * @param start the first character position in fDocument to be considered - * @param bound the first position in fDocument to not consider any more, with bound > start, or UNBOUND - * @param condition the StopCondition to check - * @return the lowest position in [start, bound) for which condition holds, or NOT_FOUND if none can be found + * @param start + * the first character position in fDocument to be + * considered + * @param bound + * the first position in fDocument to not consider + * any more, with bound > start, + * or UNBOUND + * @param condition + * the StopCondition to check + * @return the lowest position in [start, + * bound) for which condition holds, + * or NOT_FOUND if none can be found */ public int scanForward(int start, int bound, StopCondition condition) { Assert.isTrue(start >= 0); if (bound == UNBOUND) - bound= fDocument.getLength(); - + bound = fDocument.getLength(); + Assert.isTrue(bound <= fDocument.getLength()); - + try { - fPos= start; + fPos = start; while (fPos < bound) { - fChar= fDocument.getChar(fPos); + fChar = fDocument.getChar(fPos); + // omit closing tag + if (fChar == '?') { + if (fPos < fDocument.getLength() - 1) { + if (fDocument.get(fPos - 1, 2).equalsIgnoreCase("?>")) { + fPos++; + return NOT_FOUND; + } + } + } if (condition.stop(fChar, fPos, true)) return fPos; @@ -653,57 +803,102 @@ public class JavaHeuristicScanner implements Symbols { } return NOT_FOUND; } - /** - * Finds the lowest position in fDocument such that the position is >= position - * and < bound and fDocument.getChar(position) == ch evaluates to true - * and the position is in the default partition. + * Finds the lowest position in fDocument such that the + * position is >= position and < bound + * and fDocument.getChar(position) == ch evaluates to + * true and the position is in the default partition. * - * @param position the first character position in fDocument to be considered - * @param bound the first position in fDocument to not consider any more, with bound > position, or UNBOUND - * @param ch the char to search for - * @return the lowest position of ch in (bound, position] that resides in a Java partition, or NOT_FOUND if none can be found + * @param position + * the first character position in fDocument to be + * considered + * @param bound + * the first position in fDocument to not consider + * any more, with bound > position, + * or UNBOUND + * @param ch + * the char to search for + * @return the lowest position of ch in (bound, + * position] that resides in a Java partition, or + * NOT_FOUND if none can be found */ public int scanForward(int position, int bound, char ch) { return scanForward(position, bound, new CharacterMatch(ch)); } /** - * Finds the lowest position in fDocument such that the position is >= position - * and < bound and fDocument.getChar(position) == ch evaluates to true for at least one - * ch in chars and the position is in the default partition. + * Finds the lowest position in fDocument such that the + * position is >= position and < bound + * and fDocument.getChar(position) == ch evaluates to + * true for at least one ch in chars and the + * position is in the default partition. * - * @param position the first character position in fDocument to be considered - * @param bound the first position in fDocument to not consider any more, with bound > position, or UNBOUND - * @param chars an array of char to search for - * @return the lowest position of a non-whitespace character in [position, bound) that resides in a Java partition, or NOT_FOUND if none can be found + * @param position + * the first character position in fDocument to be + * considered + * @param bound + * the first position in fDocument to not consider + * any more, with bound > position, + * or UNBOUND + * @param chars + * an array of char to search for + * @return the lowest position of a non-whitespace character in [position, + * bound) that resides in a Java partition, or + * NOT_FOUND if none can be found */ public int scanForward(int position, int bound, char[] chars) { return scanForward(position, bound, new CharacterMatch(chars)); } - + /** - * Finds the highest position p in fDocument such that bound < p <= start - * and condition.stop(fDocument.getChar(p), p) evaluates to true. + * Finds the highest position p in fDocument + * such that bound < p <= + * start and + * condition.stop(fDocument.getChar(p), p) evaluates to + * true. * - * @param start the first character position in fDocument to be considered - * @param bound the first position in fDocument to not consider any more, with bound < start, or UNBOUND - * @param condition the StopCondition to check - * @return the highest position in (bound, start for which condition holds, or NOT_FOUND if none can be found + * @param start + * the first character position in fDocument to be + * considered + * @param bound + * the first position in fDocument to not consider + * any more, with bound < start, + * or UNBOUND + * @param condition + * the StopCondition to check + * @return the highest position in (bound, + * start for which condition holds, or + * NOT_FOUND if none can be found */ public int scanBackward(int start, int bound, StopCondition condition) { if (bound == UNBOUND) - bound= -1; - + bound = -1; + Assert.isTrue(bound >= -1); - Assert.isTrue(start < fDocument.getLength() ); - + Assert.isTrue(start < fDocument.getLength()); + try { - fPos= start; + fPos = start; while (fPos > bound) { - - fChar= fDocument.getChar(fPos); + + fChar = fDocument.getChar(fPos); + // omit opening tag + if (fChar == 'p' || fChar == 'P') { + if (fPos >= 4) { + if (fDocument.get(fPos - 4, 5).equalsIgnoreCase("= 1) { + if (fDocument.get(fPos - 1, 2).equalsIgnoreCase("fDocument such that the position is <= position - * and > bound and fDocument.getChar(position) == ch evaluates to true for at least one - * ch in chars and the position is in the default partition. + * Finds the highest position in fDocument such that the + * position is <= position and > bound + * and fDocument.getChar(position) == ch evaluates to + * true for at least one ch in chars and the + * position is in the default partition. * - * @param position the first character position in fDocument to be considered - * @param bound the first position in fDocument to not consider any more, with bound < position, or UNBOUND - * @param ch the char to search for - * @return the highest position of one element in chars in (bound, position] that resides in a Java partition, or NOT_FOUND if none can be found + * @param position + * the first character position in fDocument to be + * considered + * @param bound + * the first position in fDocument to not consider + * any more, with bound < position, + * or UNBOUND + * @param ch + * the char to search for + * @return the highest position of one element in chars in (bound, + * position] that resides in a Java partition, or + * NOT_FOUND if none can be found */ public int scanBackward(int position, int bound, char ch) { return scanBackward(position, bound, new CharacterMatch(ch)); } - + /** - * Finds the highest position in fDocument such that the position is <= position - * and > bound and fDocument.getChar(position) == ch evaluates to true for at least one - * ch in chars and the position is in the default partition. + * Finds the highest position in fDocument such that the + * position is <= position and > bound + * and fDocument.getChar(position) == ch evaluates to + * true for at least one ch in chars and the + * position is in the default partition. * - * @param position the first character position in fDocument to be considered - * @param bound the first position in fDocument to not consider any more, with bound < position, or UNBOUND - * @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 NOT_FOUND if none can be found + * @param position + * the first character position in fDocument to be + * considered + * @param bound + * the first position in fDocument to not consider + * any more, with bound < position, + * or UNBOUND + * @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 + * NOT_FOUND if none can be found */ public int scanBackward(int position, int bound, char[] chars) { return scanBackward(position, bound, new CharacterMatch(chars)); } - + /** - * Checks whether position resides in a default (Java) partition of fDocument. + * Checks whether position resides in a default (Java) + * partition of fDocument. * - * @param position the position to be checked - * @return true if position is in the default partition of fDocument, false otherwise + * @param position + * the position to be checked + * @return true if position is in the default + * partition of fDocument, false + * otherwise */ public boolean isDefaultPartition(int position) { Assert.isTrue(position >= 0); Assert.isTrue(position <= fDocument.getLength()); - + try { - ITypedRegion region= TextUtilities.getPartition(fDocument, fPartitioning, position, false); + ITypedRegion region = TextUtilities.getPartition(fDocument, + fPartitioning, position, false); return region.getType().equals(fPartition); - + } catch (BadLocationException e) { } - + return false; } /** - * Checks if the line seems to be an open condition not followed by a block (i.e. an if, while, - * or for statement with just one following statement, see example below). + * Checks if the line seems to be an open condition not followed by a block + * (i.e. an if, while, or for statement with just one following statement, + * see example below). * *
 	 * if (condition)
-	 *     doStuff();
+	 * 	doStuff();
 	 * 
* - *

Algorithm: if the last non-WS, non-Comment code on the line is an if (condition), while (condition), - * for( expression), do, else, and there is no statement after that

+ *

+ * Algorithm: if the last non-WS, non-Comment code on the line is an if + * (condition), while (condition), for( expression), do, else, and there is + * no statement after that + *

* - * @param position the insert position of the new character - * @param bound the lowest position to consider - * @return true if the code is a conditional statement or loop without a block, false otherwise + * @param position + * the insert position of the new character + * @param bound + * the lowest position to consider + * @return true if the code is a conditional statement or + * loop without a block, false otherwise */ public boolean isBracelessBlockStart(int position, int bound) { if (position < 1) return false; - + switch (previousToken(position, bound)) { - case TokenDO: - case TokenELSE: - return true; - case TokenRPAREN: - position= findOpeningPeer(fPos, LPAREN, RPAREN); - if (position > 0) { - switch (previousToken(position - 1, bound)) { - case TokenIF: - case TokenFOR: - case TokenWHILE: - return true; - } + case TokenDO: + case TokenELSE: + return true; + case TokenRPAREN: + position = findOpeningPeer(fPos, LPAREN, RPAREN); + if (position > 0) { + switch (previousToken(position - 1, bound)) { + case TokenIF: + case TokenFOR: + case TokenWHILE: + return true; } + } } - + return false; } }