import org.eclipse.jface.text.IDocument;
/**
- * Reads from a document either forwards or backwards. May be configured to
- * skip comments and strings.
+ * Reads from a document either forwards or backwards. May be configured to skip comments and strings.
*/
public class PHPCodeReader extends SingleCharReader {
-
- /** The EOF character */
- public static final int EOF= -1;
-
- private boolean fSkipComments= false;
- private boolean fSkipStrings= false;
- private boolean fForward= false;
-
- private IDocument fDocument;
- private int fOffset;
-
- private int fEnd= -1;
- private int fCachedLineNumber= -1;
- private int fCachedLineOffset= -1;
-
-
- public PHPCodeReader() {
- }
-
- /**
- * Returns the offset of the last read character. Should only be called after read has been called.
- */
- public int getOffset() {
- return fForward ? fOffset -1 : fOffset;
- }
-
- public void configureForwardReader(IDocument document, int offset, int length, boolean skipComments, boolean skipStrings) throws IOException {
- fDocument= document;
- fOffset= offset;
- fSkipComments= skipComments;
- fSkipStrings= skipStrings;
-
- fForward= true;
- fEnd= Math.min(fDocument.getLength(), fOffset + length);
- }
-
- public void configureBackwardReader(IDocument document, int offset, boolean skipComments, boolean skipStrings) throws IOException {
- fDocument= document;
- fOffset= offset;
- fSkipComments= skipComments;
- fSkipStrings= skipStrings;
-
- fForward= false;
- try {
- fCachedLineNumber= fDocument.getLineOfOffset(fOffset);
- } catch (BadLocationException x) {
- throw new IOException(x.getMessage());
- }
- }
-
- /*
- * @see Reader#close()
- */
- public void close() throws IOException {
- fDocument= null;
- }
-
- /*
- * @see SingleCharReader#read()
- */
- public int read() throws IOException {
- try {
- return fForward ? readForwards() : readBackwards();
- } catch (BadLocationException x) {
- throw new IOException(x.getMessage());
- }
- }
-
- private void gotoCommentEnd() throws BadLocationException {
- while (fOffset < fEnd) {
- char current= fDocument.getChar(fOffset++);
- if (current == '*') {
- if (fOffset < fEnd && fDocument.getChar(fOffset) == '/') {
- ++ fOffset;
- return;
- }
- }
- }
- }
-
- private void gotoStringEnd(char delimiter) throws BadLocationException {
- while (fOffset < fEnd) {
- char current= fDocument.getChar(fOffset++);
- if (current == '\\') {
- // ignore escaped characters
- ++ fOffset;
- } else if (current == delimiter) {
- return;
- }
- }
- }
-
- private void gotoLineEnd() throws BadLocationException {
- int line= fDocument.getLineOfOffset(fOffset);
- fOffset= fDocument.getLineOffset(line + 1);
- }
-
- private int readForwards() throws BadLocationException {
- while (fOffset < fEnd) {
- char current= fDocument.getChar(fOffset++);
-
- switch (current) {
- case '#':
-
- if (fSkipComments && fOffset < fEnd) {
- gotoLineEnd();
- continue;
+
+ /** The EOF character */
+ public static final int EOF = -1;
+
+ private boolean fSkipComments = false;
+
+ private boolean fSkipStrings = false;
+
+ private boolean fForward = false;
+
+ private IDocument fDocument;
+
+ private int fOffset;
+
+ private int fEnd = -1;
+
+ private int fCachedLineNumber = -1;
+
+ private int fCachedLineOffset = -1;
+
+ public PHPCodeReader() {
+ }
+
+ /**
+ * Returns the offset of the last read character. Should only be called after read has been called.
+ */
+ public int getOffset() {
+ return fForward ? fOffset - 1 : fOffset;
+ }
+
+ public void configureForwardReader(IDocument document, int offset, int length, boolean skipComments, boolean skipStrings)
+ throws IOException {
+ fDocument = document;
+ fOffset = offset;
+ fSkipComments = skipComments;
+ fSkipStrings = skipStrings;
+
+ fForward = true;
+ fEnd = Math.min(fDocument.getLength(), fOffset + length);
+ }
+
+ public void configureBackwardReader(IDocument document, int offset, boolean skipComments, boolean skipStrings) throws IOException {
+ fDocument = document;
+ fOffset = offset;
+ fSkipComments = skipComments;
+ fSkipStrings = skipStrings;
+
+ fForward = false;
+ try {
+ fCachedLineNumber = fDocument.getLineOfOffset(fOffset);
+ } catch (BadLocationException x) {
+ throw new IOException(x.getMessage());
+ }
+ }
+
+ /*
+ * @see Reader#close()
+ */
+ public void close() throws IOException {
+ fDocument = null;
+ }
+
+ /*
+ * @see SingleCharReader#read()
+ */
+ public int read() throws IOException {
+ try {
+ return fForward ? readForwards() : readBackwards();
+ } catch (BadLocationException x) {
+ throw new IOException(x.getMessage());
+ }
+ }
+
+ private void gotoCommentEnd() throws BadLocationException {
+ while (fOffset < fEnd) {
+ char current = fDocument.getChar(fOffset++);
+ if (current == '*') {
+ if (fOffset < fEnd && fDocument.getChar(fOffset) == '/') {
+ ++fOffset;
+ return;
+ }
+ }
+ }
+ }
+
+ private void gotoStringEnd(char delimiter) throws BadLocationException {
+ while (fOffset < fEnd) {
+ char current = fDocument.getChar(fOffset++);
+ if (current == '\\') {
+ // ignore escaped characters
+ ++fOffset;
+ } else if (current == delimiter) {
+ return;
+ }
+ }
+ }
+
+ private void gotoLineEnd() throws BadLocationException {
+ int line = fDocument.getLineOfOffset(fOffset);
+ fOffset = fDocument.getLineOffset(line + 1);
+ }
+
+ private int readForwards() throws BadLocationException {
+ while (fOffset < fEnd) {
+ char current = fDocument.getChar(fOffset++);
+
+ switch (current) {
+ case '"':
+ case '\'':
+
+ if (fSkipStrings) {
+ gotoStringEnd(current);
+ continue;
+ }
+
+ return current;
+ case '#':
+
+ if (fSkipComments && fOffset < fEnd) {
+ gotoLineEnd();
+ continue;
+ }
+
+ return current;
+
+ case '/':
+
+ if (fSkipComments && fOffset < fEnd) {
+ char next = fDocument.getChar(fOffset);
+ if (next == '*') {
+ // a comment starts, advance to the comment end
+ ++fOffset;
+ gotoCommentEnd();
+ continue;
+ } else if (next == '/') {
+ // '//'-comment starts, advance to the line end
+ gotoLineEnd();
+ continue;
}
-
- return current;
-
- case '/':
-
- if (fSkipComments && fOffset < fEnd) {
- char next= fDocument.getChar(fOffset);
- if (next == '*') {
- // a comment starts, advance to the comment end
- ++ fOffset;
- gotoCommentEnd();
- continue;
- } else if (next == '/') {
- // '//'-comment starts, advance to the line end
- gotoLineEnd();
- continue;
- }
- }
-
- return current;
-
- case '"':
- case '\'':
-
- if (fSkipStrings) {
- gotoStringEnd(current);
- continue;
- }
-
- return current;
- }
-
- return current;
- }
-
- return EOF;
- }
-
- private void handleSingleLineComment() throws BadLocationException {
- int line= fDocument.getLineOfOffset(fOffset);
- if (line < fCachedLineNumber) {
- fCachedLineNumber= line;
- fCachedLineOffset= fDocument.getLineOffset(line);
- int offset= fOffset;
- while (fCachedLineOffset < offset) {
- char current= fDocument.getChar(offset--);
- if (current == '/' && fCachedLineOffset <= offset && fDocument.getChar(offset) == '/') {
- fOffset= offset;
- return;
- }
+ }
+
+ return current;
+
+ }
+
+ return current;
+ }
+
+ return EOF;
+ }
+
+ private void handleSingleLineComment() throws BadLocationException {
+ int line = fDocument.getLineOfOffset(fOffset);
+ if (line < fCachedLineNumber) {
+ fCachedLineNumber = line;
+ fCachedLineOffset = fDocument.getLineOffset(line);
+ int offset = fOffset;
+ while (fCachedLineOffset < offset) {
+ char current = fDocument.getChar(offset--);
+
+ if (current == '/' && fCachedLineOffset <= offset && fDocument.getChar(offset) == '/') {
+ fOffset = offset;
+ return;
+ }
+
if (current == '#' && fCachedLineOffset <= offset) {
- fOffset= offset;
+ fOffset = offset;
return;
}
- }
- }
- }
-
- private void gotoCommentStart() throws BadLocationException {
- while (0 < fOffset) {
- char current= fDocument.getChar(fOffset--);
- if (current == '*' && 0 <= fOffset && fDocument.getChar(fOffset) == '/')
- return;
- }
- }
-
- private void gotoStringStart(char delimiter) throws BadLocationException {
- while (0 < fOffset) {
- char current= fDocument.getChar(fOffset);
- if (current == delimiter) {
- if ( !(0 <= fOffset && fDocument.getChar(fOffset -1) == '\\'))
- return;
- }
- -- fOffset;
- }
- }
-
- private int readBackwards() throws BadLocationException {
-
- while (0 < fOffset) {
- -- fOffset;
-
- handleSingleLineComment();
-
- char current= fDocument.getChar(fOffset);
- switch (current) {
- case '/':
-
- if (fSkipComments && fOffset > 1) {
- char next= fDocument.getChar(fOffset - 1);
- if (next == '*') {
- // a comment ends, advance to the comment start
- fOffset -= 2;
- gotoCommentStart();
- continue;
- }
- }
-
- return current;
-
- case '"':
- case '\'':
-
- if (fSkipStrings) {
- -- fOffset;
- gotoStringStart(current);
- continue;
- }
-
- return current;
- }
-
- return current;
- }
-
- return EOF;
- }
+ }
+ }
+ }
+
+ private void gotoCommentStart() throws BadLocationException {
+ while (0 < fOffset) {
+ char current = fDocument.getChar(fOffset--);
+ if (current == '*' && 0 <= fOffset && fDocument.getChar(fOffset) == '/')
+ return;
+ }
+ }
+
+ private void gotoStringStart(char delimiter) throws BadLocationException {
+ while (0 < fOffset) {
+ char current = fDocument.getChar(fOffset);
+ if (current == delimiter) {
+ if (!(0 <= fOffset && fDocument.getChar(fOffset - 1) == '\\'))
+ return;
+ }
+ --fOffset;
+ }
+ }
+
+ private int readBackwards() throws BadLocationException {
+
+ while (0 < fOffset) {
+ --fOffset;
+
+ handleSingleLineComment();
+
+ char current = fDocument.getChar(fOffset);
+ switch (current) {
+ case '/':
+
+ if (fSkipComments && fOffset > 1) {
+ char next = fDocument.getChar(fOffset - 1);
+ if (next == '*') {
+ // a comment ends, advance to the comment start
+ fOffset -= 2;
+ gotoCommentStart();
+ continue;
+ }
+ }
+
+ return current;
+ case '"':
+ case '\'':
+
+ if (fSkipStrings) {
+ --fOffset;
+ gotoStringStart(current);
+ continue;
+ }
+
+ return current;
+ }
+
+ return current;
+ }
+
+ return EOF;
+ }
}
* Helper class for match pairs of characters.
*/
public class PHPPairMatcher implements ICharacterPairMatcher {
-
-
- public static final int LEFT= 1;
- public static final int RIGHT= 2;
-
-
- protected char[] fPairs;
- protected IDocument fDocument;
- protected int fOffset;
-
- protected int fStartPos;
- protected int fEndPos;
- protected int fAnchor;
-
- protected PHPCodeReader fReader= new PHPCodeReader();
-
-
- public PHPPairMatcher(char[] pairs) {
- fPairs= pairs;
- }
-
- /*
- * @see org.eclipse.jface.text.source.ICharacterPairMatcher#clear()
- */
- public void clear() {
- if (fReader != null) {
- try {
- fReader.close();
- } catch (IOException x) {
- // ignore
- }
- }
- }
-
- public IRegion match(IDocument document, int offset) {
-
- fOffset= offset;
-
- if (fOffset < 0)
- return null;
-
- fDocument= document;
-
- if (matchPairsAt() && fStartPos != fEndPos)
- return new Region(fStartPos, fEndPos - fStartPos + 1);
-
- return null;
- }
-
- public int getAnchor() {
- return fAnchor;
- }
-
- public void dispose() {
- fDocument= null;
- if (fReader != null) {
- try {
- fReader.close();
- } catch (IOException x) {
- // ignore
- }
- fReader= null;
- }
- }
-
- protected boolean matchPairsAt() {
-
- int i;
- int pairIndex1= fPairs.length;
- int pairIndex2= fPairs.length;
-
- fStartPos= -1;
- fEndPos= -1;
-
- // get the chars preceding and following the start position
- try {
-
- char prevChar= fDocument.getChar(Math.max(fOffset - 1, 0));
- char nextChar= fDocument.getChar(fOffset);
-
- // search for opening peer character next to the activation point
- for (i= 0; i < fPairs.length; i= i + 2) {
- if (nextChar == fPairs[i]) {
- fStartPos= fOffset;
- pairIndex1= i;
- } else if (prevChar == fPairs[i]) {
- fStartPos= fOffset - 1;
- pairIndex1= i;
- }
- }
-
- // search for closing peer character next to the activation point
- for (i= 1; i < fPairs.length; i= i + 2) {
- if (prevChar == fPairs[i]) {
- fEndPos= fOffset - 1;
- pairIndex2= i;
- } else if (nextChar == fPairs[i]) {
- fEndPos= fOffset;
- pairIndex2= i;
- }
- }
-
- if (fEndPos > -1) {
- fAnchor= RIGHT;
- fStartPos= searchForOpeningPeer(fEndPos, fPairs[pairIndex2 - 1], fPairs[pairIndex2], fDocument);
- if (fStartPos > -1)
- return true;
- else
- fEndPos= -1;
- } else if (fStartPos > -1) {
- fAnchor= LEFT;
- fEndPos= searchForClosingPeer(fStartPos, fPairs[pairIndex1], fPairs[pairIndex1 + 1], fDocument);
- if (fEndPos > -1)
- return true;
- else
- fStartPos= -1;
- }
-
- } catch (BadLocationException x) {
- } catch (IOException x) {
- }
-
- return false;
- }
-
- protected int searchForClosingPeer(int offset, int openingPeer, int closingPeer, IDocument document) throws IOException {
-
- fReader.configureForwardReader(document, offset + 1, document.getLength(), true, true);
-
- int stack= 1;
- int c= fReader.read();
- while (c != PHPCodeReader.EOF) {
- if (c == openingPeer && c != closingPeer)
- stack++;
- else if (c == closingPeer)
- stack--;
-
- if (stack == 0)
- return fReader.getOffset();
-
- c= fReader.read();
- }
-
- return -1;
- }
-
- protected int searchForOpeningPeer(int offset, int openingPeer, int closingPeer, IDocument document) throws IOException {
-
- fReader.configureBackwardReader(document, offset, true, true);
-
- int stack= 1;
- int c= fReader.read();
- while (c != PHPCodeReader.EOF) {
- if (c == closingPeer && c != openingPeer)
- stack++;
- else if (c == openingPeer)
- stack--;
-
- if (stack == 0)
- return fReader.getOffset();
-
- c= fReader.read();
- }
-
- return -1;
- }
-}
+ protected char[] fPairs;
+
+ protected IDocument fDocument;
+
+ protected int fOffset;
+
+ protected int fStartPos;
+
+ protected int fEndPos;
+
+ protected int fAnchor;
+
+ protected PHPCodeReader fReader = new PHPCodeReader();
+
+ public PHPPairMatcher(char[] pairs) {
+ fPairs = pairs;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.source.ICharacterPairMatcher#clear()
+ */
+ public void clear() {
+ if (fReader != null) {
+ try {
+ fReader.close();
+ } catch (IOException x) {
+ // ignore
+ }
+ }
+ }
+
+ public IRegion match(IDocument document, int offset) {
+
+ fOffset = offset;
+
+ if (fOffset < 0)
+ return null;
+
+ fDocument = document;
+
+ if (matchPairsAt() && fStartPos != fEndPos)
+ return new Region(fStartPos, fEndPos - fStartPos + 1);
+
+ return null;
+ }
+
+ public int getAnchor() {
+ return fAnchor;
+ }
+
+ public void dispose() {
+ fDocument = null;
+ if (fReader != null) {
+ try {
+ fReader.close();
+ } catch (IOException x) {
+ // ignore
+ }
+ fReader = null;
+ }
+ }
+
+ protected boolean matchPairsAt() {
+
+ int i;
+ int pairIndex1 = fPairs.length;
+ int pairIndex2 = fPairs.length;
+
+ fStartPos = -1;
+ fEndPos = -1;
+
+ // get the chars preceding and following the start position
+ try {
+
+ char prevChar = fDocument.getChar(Math.max(fOffset - 1, 0));
+ char nextChar = fDocument.getChar(fOffset);
+
+ // search for opening peer character next to the activation point
+ for (i = 0; i < fPairs.length; i = i + 2) {
+ if (nextChar == fPairs[i]) {
+ fStartPos = fOffset;
+ pairIndex1 = i;
+ } else if (prevChar == fPairs[i]) {
+ fStartPos = fOffset - 1;
+ pairIndex1 = i;
+ }
+ }
+
+ // search for closing peer character next to the activation point
+ for (i = 1; i < fPairs.length; i = i + 2) {
+ if (prevChar == fPairs[i]) {
+ fEndPos = fOffset - 1;
+ pairIndex2 = i;
+ } else if (nextChar == fPairs[i]) {
+ fEndPos = fOffset;
+ pairIndex2 = i;
+ }
+ }
+
+ if (fEndPos > -1) {
+ fAnchor = RIGHT;
+ fStartPos = searchForOpeningPeer(fEndPos, fPairs[pairIndex2 - 1], fPairs[pairIndex2], fDocument);
+ if (fStartPos > -1)
+ return true;
+ else
+ fEndPos = -1;
+ } else if (fStartPos > -1) {
+ fAnchor = LEFT;
+ fEndPos = searchForClosingPeer(fStartPos, fPairs[pairIndex1], fPairs[pairIndex1 + 1], fDocument);
+ if (fEndPos > -1)
+ return true;
+ else
+ fStartPos = -1;
+ }
+
+ } catch (BadLocationException x) {
+ } catch (IOException x) {
+ }
+
+ return false;
+ }
+
+ protected int searchForClosingPeer(int offset, int openingPeer, int closingPeer, IDocument document) throws IOException {
+
+ fReader.configureForwardReader(document, offset + 1, document.getLength(), true, true);
+
+ int stack = 1;
+ int c = fReader.read();
+ while (c != PHPCodeReader.EOF) {
+ if (c == openingPeer && c != closingPeer)
+ stack++;
+ else if (c == closingPeer)
+ stack--;
+
+ if (stack == 0)
+ return fReader.getOffset();
+
+ c = fReader.read();
+ }
+
+ return -1;
+ }
+
+ protected int searchForOpeningPeer(int offset, int openingPeer, int closingPeer, IDocument document) throws IOException {
+
+ fReader.configureBackwardReader(document, offset, true, true);
+
+ int stack = 1;
+ int c = fReader.read();
+ while (c != PHPCodeReader.EOF) {
+ if (c == closingPeer && c != openingPeer)
+ stack++;
+ else if (c == openingPeer)
+ stack--;
+
+ if (stack == 0)
+ return fReader.getOffset();
+
+ c = fReader.read();
+ }
+
+ return -1;
+ }
+}
\ No newline at end of file