1 /*******************************************************************************
2 * Copyright (c) 2000, 2004 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v10.html
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package net.sourceforge.phpdt.internal.ui.text;
13 import net.sourceforge.phpeclipse.ui.text.rules.AbstractPartitioner;
15 import org.eclipse.jface.text.Assert;
16 import org.eclipse.jface.text.IDocument;
17 import org.eclipse.jface.text.rules.ICharacterScanner;
18 import org.eclipse.jface.text.rules.IPartitionTokenScanner;
19 import org.eclipse.jface.text.rules.IToken;
20 import org.eclipse.jface.text.rules.Token;
23 * This scanner recognizes the JavaDoc comments, Java multi line comments, Java single line comments, Java strings.
25 public class FastJavaPartitionScanner implements IPartitionTokenScanner, IPHPPartitions {
28 private static final int PHP = 0;
30 private static final int SINGLE_LINE_COMMENT = 1;
32 private static final int MULTI_LINE_COMMENT = 2;
34 private static final int PHPDOC = 3;
36 private static final int STRING_DQ = 4;
38 private static final int STRING_SQ = 5;
40 // private static final int CHARACTER= 4;
42 // beginning of prefixes and postfixes
43 private static final int NONE = 0;
45 private static final int BACKSLASH = 1; // postfix for STRING_DQ and CHARACTER
47 private static final int SLASH = 2; // prefix for SINGLE_LINE or MULTI_LINE or JAVADOC
49 private static final int SLASH_STAR = 3; // prefix for MULTI_LINE_COMMENT or JAVADOC
51 private static final int SLASH_STAR_STAR = 4; // prefix for MULTI_LINE_COMMENT or JAVADOC
53 private static final int STAR = 5; // postfix for MULTI_LINE_COMMENT or JAVADOC
55 private static final int CARRIAGE_RETURN = 6; // postfix for STRING_DQ, CHARACTER and SINGLE_LINE_COMMENT
58 private final BufferedDocumentScanner fScanner = new BufferedDocumentScanner(1000); // faster implementation
60 /** The offset of the last returned token. */
61 private int fTokenOffset;
63 /** The length of the last returned token. */
64 private int fTokenLength;
66 /** The state of the scanner. */
69 /** The last significant characters read. */
72 /** The amount of characters already read on first call to nextToken(). */
73 private int fPrefixLength;
75 // emulate JavaPartitionScanner
76 private boolean fEmulate = false;
78 private int fJavaOffset;
80 private int fJavaLength;
82 private final IToken[] fTokens = new IToken[] {
84 new Token(PHP_SINGLELINE_COMMENT),
85 new Token(PHP_MULTILINE_COMMENT),
86 new Token(PHP_PHPDOC_COMMENT),
87 new Token(PHP_STRING_DQ),
88 new Token(PHP_STRING_SQ) };
90 public FastJavaPartitionScanner(boolean emulate) {
94 public FastJavaPartitionScanner() {
99 * @see org.eclipse.jface.text.rules.ITokenScanner#nextToken()
101 public IToken nextToken() {
103 // emulate JavaPartitionScanner
105 if (fJavaOffset != -1 && fTokenOffset + fTokenLength != fJavaOffset + fJavaLength) {
106 fTokenOffset += fTokenLength;
114 fTokenOffset += fTokenLength;
115 fTokenLength = fPrefixLength;
118 final int ch = fScanner.read();
122 case ICharacterScanner.EOF:
123 if (fTokenLength > 0) {
124 fLast = NONE; // ignore last
125 return preFix(fState, PHP, NONE, 0);
134 // emulate JavaPartitionScanner
135 if (!fEmulate && fLast != CARRIAGE_RETURN) {
136 fLast = CARRIAGE_RETURN;
143 case SINGLE_LINE_COMMENT:
147 if (fTokenLength > 0) {
148 IToken token = fTokens[fState];
150 // emulate JavaPartitionScanner
156 fLast = CARRIAGE_RETURN;
176 case SINGLE_LINE_COMMENT:
180 // assert(fTokenLength > 0);
181 return postFix(fState);
189 if (fState == SINGLE_LINE_COMMENT) {
190 int nextch = fScanner.read();
192 // <h1>This is an <?php # echo 'simple' ?> example.</h1>
196 return postFix(fState);
202 if (!fEmulate && fLast == CARRIAGE_RETURN) {
204 case SINGLE_LINE_COMMENT:
223 newState = STRING_SQ;
228 newState = STRING_DQ;
232 last = CARRIAGE_RETURN;
247 fLast = NONE; // ignore fLast
248 return preFix(fState, newState, last, 1);
261 if (fTokenLength > 0) {
262 return preFix(PHP, SINGLE_LINE_COMMENT, NONE, 1);
264 preFix(PHP, SINGLE_LINE_COMMENT, NONE, 1);
265 fTokenOffset += fTokenLength;
266 fTokenLength = fPrefixLength;
270 if (fLast == SLASH) {
271 if (fTokenLength - getLastLength(fLast) > 0) {
272 return preFix(PHP, SINGLE_LINE_COMMENT, NONE, 2);
274 preFix(PHP, SINGLE_LINE_COMMENT, NONE, 2);
275 fTokenOffset += fTokenLength;
276 fTokenLength = fPrefixLength;
287 if (fLast == SLASH) {
288 if (fTokenLength - getLastLength(fLast) > 0)
289 return preFix(PHP, MULTI_LINE_COMMENT, SLASH_STAR, 2);
291 preFix(PHP, MULTI_LINE_COMMENT, SLASH_STAR, 2);
292 fTokenOffset += fTokenLength;
293 fTokenLength = fPrefixLength;
303 fLast = NONE; // ignore fLast
304 if (fTokenLength > 0)
305 return preFix(PHP, STRING_SQ, NONE, 1);
307 preFix(PHP, STRING_SQ, NONE, 1);
308 fTokenOffset += fTokenLength;
309 fTokenLength = fPrefixLength;
314 fLast = NONE; // ignore fLast
315 if (fTokenLength > 0)
316 return preFix(PHP, STRING_DQ, NONE, 1);
318 preFix(PHP, STRING_DQ, NONE, 1);
319 fTokenOffset += fTokenLength;
320 fTokenLength = fPrefixLength;
330 case SINGLE_LINE_COMMENT:
338 case SLASH_STAR_STAR:
339 return postFix(MULTI_LINE_COMMENT);
342 return postFix(PHPDOC);
361 case MULTI_LINE_COMMENT:
364 if (fLast == SLASH_STAR) {
365 fLast = SLASH_STAR_STAR;
376 return postFix(MULTI_LINE_COMMENT);
391 fLast = (fLast == BACKSLASH) ? NONE : BACKSLASH;
396 if (fLast != BACKSLASH) {
397 return postFix(STRING_DQ);
412 fLast = (fLast == BACKSLASH) ? NONE : BACKSLASH;
417 if (fLast != BACKSLASH) {
418 return postFix(STRING_SQ);
433 // fLast= (fLast == BACKSLASH) ? NONE : BACKSLASH;
438 // if (fLast != BACKSLASH) {
439 // return postFix(CHARACTER);
455 private static final int getLastLength(int last) {
463 case CARRIAGE_RETURN:
472 case SLASH_STAR_STAR:
477 private final void consume() {
482 private final IToken postFix(int state) {
487 return fTokens[state];
490 private final IToken preFix(int state, int newState, int last, int prefixLength) {
491 // emulate JavaPartitionScanner
492 if (fEmulate && state == PHP && (fTokenLength - getLastLength(fLast) > 0)) {
493 fTokenLength -= getLastLength(fLast);
494 fJavaOffset = fTokenOffset;
495 fJavaLength = fTokenLength;
498 fPrefixLength = prefixLength;
500 return fTokens[state];
503 fTokenLength -= getLastLength(fLast);
505 fPrefixLength = prefixLength;
506 IToken token = fTokens[state];
512 private static int getState(String contentType) {
514 if (contentType == null)
517 else if (contentType.equals(PHP_SINGLELINE_COMMENT))
518 return SINGLE_LINE_COMMENT;
520 else if (contentType.equals(PHP_MULTILINE_COMMENT))
521 return MULTI_LINE_COMMENT;
523 else if (contentType.equals(PHP_PHPDOC_COMMENT))
526 else if (contentType.equals(PHP_STRING_DQ))
529 else if (contentType.equals(PHP_STRING_SQ))
531 // else if (contentType.equals(JAVA_CHARACTER))
539 * @see IPartitionTokenScanner#setPartialRange(IDocument, int, int, String, int)
541 public void setPartialRange(IDocument document, int offset, int length, String contentType, int partitionOffset) {
542 fScanner.setRange(document, offset, length);
543 setRange(document, offset, length);
544 fTokenOffset = partitionOffset;
546 fPrefixLength = offset - partitionOffset;
549 if (offset == partitionOffset) {
550 // restart at beginning of partition
553 fState = getState(contentType);
556 // emulate JavaPartitionScanner
564 * @see ITokenScanner#setRange(IDocument, int, int)
566 public void setRange(IDocument document, int offset, int length) {
567 fScanner.setRange(document, offset, length);
568 fTokenOffset = offset;
574 // emulate JavaPartitionScanner
582 * @see ITokenScanner#getTokenLength()
584 public int getTokenLength() {
589 * @see ITokenScanner#getTokenOffset()
591 public int getTokenOffset() {
592 if (AbstractPartitioner.DEBUG) {
593 Assert.isTrue(fTokenOffset >= 0, Integer.toString(fTokenOffset));