Added PHPUnitEditor and corresponding PHPPreferencePage
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / ui / text / FastJavaPartitionScanner.java
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 (file)
index 0000000..41246b6
--- /dev/null
@@ -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;
+       }
+
+}