X-Git-Url: http://git.phpeclipse.com diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/FastJavaPartitionScanner.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/FastJavaPartitionScanner.java new file mode 100644 index 0000000..41246b6 --- /dev/null +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/FastJavaPartitionScanner.java @@ -0,0 +1,526 @@ +package net.sourceforge.phpdt.internal.ui.text; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.rules.ICharacterScanner; +import org.eclipse.jface.text.rules.IPartitionTokenScanner; +import org.eclipse.jface.text.rules.IToken; +import org.eclipse.jface.text.rules.Token; + + +/** + * This scanner recognizes the JavaDoc comments, Java multi line comments, Java single line comments, + * Java strings and Java characters. + */ +public class FastJavaPartitionScanner implements IPartitionTokenScanner { + + private final static String SKIP= "__skip"; //$NON-NLS-1$ + public final static String JAVA_STRING= "__php_string"; //$NON-NLS-1$ + public final static String JAVA_SINGLE_LINE_COMMENT= "__php_singleline_comment"; //$NON-NLS-1$ + public final static String JAVA_MULTI_LINE_COMMENT= "__php_multiline_comment"; //$NON-NLS-1$ + public final static String JAVA_DOC= "__php_phpdoc"; //$NON-NLS-1$ + + // states + private static final int JAVA= 0; + private static final int SINGLE_LINE_COMMENT= 1; + private static final int MULTI_LINE_COMMENT= 2; + private static final int JAVADOC= 3; + private static final int CHARACTER= 4; + private static final int STRING= 5; + + // beginning of prefixes and postfixes + private static final int NONE= 0; + private static final int BACKSLASH= 1; // postfix for STRING and CHARACTER + private static final int SLASH= 2; // prefix for SINGLE_LINE or MULTI_LINE or JAVADOC + private static final int SLASH_STAR= 3; // prefix for MULTI_LINE_COMMENT or JAVADOC + private static final int SLASH_STAR_STAR= 4; // prefix for MULTI_LINE_COMMENT or JAVADOC + private static final int STAR= 5; // postfix for MULTI_LINE_COMMENT or JAVADOC + private static final int CARRIAGE_RETURN=6; // postfix for STRING, CHARACTER and SINGLE_LINE_COMMENT + + /** The scanner. */ +// private final BufferedRuleBasedScanner fScanner= new BufferedRuleBasedScanner(1000); + private final BufferedDocumentScanner fScanner= new BufferedDocumentScanner(1000); // faster implementation + + /** The offset of the last returned token. */ + private int fTokenOffset; + /** The length of the last returned token. */ + private int fTokenLength; + + /** The state of the scanner. */ + private int fState; + /** The last significant characters read. */ + private int fLast; + /** The amount of characters already read on first call to nextToken(). */ + private int fPrefixLength; + + // emulate JavaPartitionScanner + private static final boolean fgEmulate= false; + private int fJavaOffset; + private int fJavaLength; + + private final IToken[] fTokens= new IToken[] { + new Token(null), + new Token(JAVA_SINGLE_LINE_COMMENT), + new Token(JAVA_MULTI_LINE_COMMENT), + new Token(JAVA_DOC), + new Token(SKIP), + new Token(JAVA_STRING) + }; + + /* + * @see org.eclipse.jface.text.rules.ITokenScanner#nextToken() + */ + public IToken nextToken() { + + // emulate JavaPartitionScanner + if (fgEmulate) { + if (fJavaOffset != -1 && fTokenOffset + fTokenLength != fJavaOffset + fJavaLength) { + fTokenOffset += fTokenLength; + return fTokens[JAVA]; + } else { + fJavaOffset= -1; + fJavaLength= 0; + } + } + + fTokenOffset += fTokenLength; + fTokenLength= fPrefixLength; + + while (true) { + final int ch= fScanner.read(); + + // characters + switch (ch) { + case ICharacterScanner.EOF: + if (fTokenLength > 0) { + fLast= NONE; // ignore last + return preFix(fState, JAVA, NONE, 0); + + } else { + fLast= NONE; + fPrefixLength= 0; + return Token.EOF; + } + + case '\r': + // emulate JavaPartitionScanner + if (!fgEmulate && fLast != CARRIAGE_RETURN) { + fLast= CARRIAGE_RETURN; + fTokenLength++; + continue; + + } else { + + switch (fState) { + case SINGLE_LINE_COMMENT: + case CHARACTER: + case STRING: + if (fTokenLength > 0) { + IToken token= fTokens[fState]; + + // emulate JavaPartitionScanner + if (fgEmulate) { + fTokenLength++; + fLast= NONE; + fPrefixLength= 0; + } else { + fLast= CARRIAGE_RETURN; + fPrefixLength= 1; + } + + fState= JAVA; + return token; + + } else { + consume(); + continue; + } + + default: + consume(); + continue; + } + } + + case '\n': + switch (fState) { + case SINGLE_LINE_COMMENT: + case CHARACTER: + case STRING: + // assert(fTokenLength > 0); + return postFix(fState); + + default: + consume(); + continue; + } + + default: + if (!fgEmulate && fLast == CARRIAGE_RETURN) { + switch (fState) { + case SINGLE_LINE_COMMENT: + case CHARACTER: + case STRING: + + int last; + int newState; + switch (ch) { + case '/': + last= SLASH; + newState= JAVA; + break; + + case '*': + last= STAR; + newState= JAVA; + break; + + case '\'': + last= NONE; + newState= CHARACTER; + break; + + case '"': + last= NONE; + newState= STRING; + break; + + case '\r': + last= CARRIAGE_RETURN; + newState= JAVA; + break; + + case '\\': + last= BACKSLASH; + newState= JAVA; + break; + + default: + last= NONE; + newState= JAVA; + break; + } + + fLast= NONE; // ignore fLast + return preFix(fState, newState, last, 1); + + default: + break; + } + } + } + + // states + switch (fState) { + case JAVA: + switch (ch) { + case '/': + if (fLast == SLASH) { + if (fTokenLength - getLastLength(fLast) > 0) { + return preFix(JAVA, SINGLE_LINE_COMMENT, NONE, 2); + } else { + preFix(JAVA, SINGLE_LINE_COMMENT, NONE, 2); + fTokenOffset += fTokenLength; + fTokenLength= fPrefixLength; + break; + } + + } else { + fTokenLength++; + fLast= SLASH; + break; + } + + case '*': + if (fLast == SLASH) { + if (fTokenLength - getLastLength(fLast) > 0) + return preFix(JAVA, MULTI_LINE_COMMENT, SLASH_STAR, 2); + else { + preFix(JAVA, MULTI_LINE_COMMENT, SLASH_STAR, 2); + fTokenOffset += fTokenLength; + fTokenLength= fPrefixLength; + break; + } + + } else { + consume(); + break; + } + + case '\'': + fLast= NONE; // ignore fLast + if (fTokenLength > 0) + return preFix(JAVA, CHARACTER, NONE, 1); + else { + preFix(JAVA, CHARACTER, NONE, 1); + fTokenOffset += fTokenLength; + fTokenLength= fPrefixLength; + break; + } + + case '"': + fLast= NONE; // ignore fLast + if (fTokenLength > 0) + return preFix(JAVA, STRING, NONE, 1); + else { + preFix(JAVA, STRING, NONE, 1); + fTokenOffset += fTokenLength; + fTokenLength= fPrefixLength; + break; + } + + default: + consume(); + break; + } + break; + + case SINGLE_LINE_COMMENT: + consume(); + break; + + case JAVADOC: + switch (ch) { + case '/': + switch (fLast) { + case SLASH_STAR_STAR: + return postFix(MULTI_LINE_COMMENT); + + case STAR: + return postFix(JAVADOC); + + default: + consume(); + break; + } + break; + + case '*': + fTokenLength++; + fLast= STAR; + break; + + default: + consume(); + break; + } + break; + + case MULTI_LINE_COMMENT: + switch (ch) { + case '*': + if (fLast == SLASH_STAR) { + fLast= SLASH_STAR_STAR; + fTokenLength++; + fState= JAVADOC; + } else { + fTokenLength++; + fLast= STAR; + } + break; + + case '/': + if (fLast == STAR) { + return postFix(MULTI_LINE_COMMENT); + } else { + consume(); + break; + } + + default: + consume(); + break; + } + break; + + case STRING: + switch (ch) { + case '\\': + fLast= (fLast == BACKSLASH) ? NONE : BACKSLASH; + fTokenLength++; + break; + + case '\"': + if (fLast != BACKSLASH) { + return postFix(STRING); + + } else { + consume(); + break; + } + + default: + consume(); + break; + } + break; + + case CHARACTER: + switch (ch) { + case '\\': + fLast= (fLast == BACKSLASH) ? NONE : BACKSLASH; + fTokenLength++; + break; + + case '\'': + if (fLast != BACKSLASH) { + return postFix(CHARACTER); + + } else { + consume(); + break; + } + + default: + consume(); + break; + } + break; + } + } + } + + private static final int getLastLength(int last) { + switch (last) { + default: + return -1; + + case NONE: + return 0; + + case CARRIAGE_RETURN: + case BACKSLASH: + case SLASH: + case STAR: + return 1; + + case SLASH_STAR: + return 2; + + case SLASH_STAR_STAR: + return 3; + } + } + + private final void consume() { + fTokenLength++; + fLast= NONE; + } + + private final IToken postFix(int state) { + fTokenLength++; + fLast= NONE; + fState= JAVA; + fPrefixLength= 0; + return fTokens[state]; + } + + private final IToken preFix(int state, int newState, int last, int prefixLength) { + // emulate JavaPartitionScanner + if (fgEmulate && state == JAVA && (fTokenLength - getLastLength(fLast) > 0)) { + fTokenLength -= getLastLength(fLast); + fJavaOffset= fTokenOffset; + fJavaLength= fTokenLength; + fTokenLength= 1; + fState= newState; + fPrefixLength= prefixLength; + fLast= last; + return fTokens[state]; + + } else { + fTokenLength -= getLastLength(fLast); + fLast= last; + fPrefixLength= prefixLength; + IToken token= fTokens[state]; + fState= newState; + return token; + } + } + + private static int getState(String contentType) { + + if (contentType == null) + return JAVA; + + else if (contentType.equals(JAVA_SINGLE_LINE_COMMENT)) + return SINGLE_LINE_COMMENT; + + else if (contentType.equals(JAVA_MULTI_LINE_COMMENT)) + return MULTI_LINE_COMMENT; + + else if (contentType.equals(JAVA_DOC)) + return JAVADOC; + + else if (contentType.equals(JAVA_STRING)) + return STRING; + + else if (contentType.equals(SKIP)) + return CHARACTER; + + else + return JAVA; + } + + /* + * @see IPartitionTokenScanner#setPartialRange(IDocument, int, int, String, int) + */ + public void setPartialRange(IDocument document, int offset, int length, String contentType, int partitionOffset) { + + fScanner.setRange(document, offset, length); + fTokenOffset= partitionOffset; + fTokenLength= 0; + fPrefixLength= offset - partitionOffset; + fLast= NONE; + + if (offset == partitionOffset) { + // restart at beginning of partition + fState= JAVA; + } else { + fState= getState(contentType); + } + + // emulate JavaPartitionScanner + if (fgEmulate) { + fJavaOffset= -1; + fJavaLength= 0; + } + } + + /* + * @see ITokenScanner#setRange(IDocument, int, int) + */ + public void setRange(IDocument document, int offset, int length) { + + fScanner.setRange(document, offset, length); + fTokenOffset= offset; + fTokenLength= 0; + fPrefixLength= 0; + fLast= NONE; + fState= JAVA; + + // emulate JavaPartitionScanner + if (fgEmulate) { + fJavaOffset= -1; + fJavaLength= 0; + } + } + + /* + * @see ITokenScanner#getTokenLength() + */ + public int getTokenLength() { + return fTokenLength; + } + + /* + * @see ITokenScanner#getTokenOffset() + */ + public int getTokenOffset() { + return fTokenOffset; + } + +}