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 STRING_HEREDOC = 6;
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
57 // private static final int HEREDOC = 7;
60 private final BufferedDocumentScanner fScanner = new BufferedDocumentScanner(1000); // faster implementation
62 /** The offset of the last returned token. */
63 private int fTokenOffset;
65 /** The length of the last returned token. */
66 private int fTokenLength;
68 /** The state of the scanner. */
71 /** The last significant characters read. */
74 /** The amount of characters already read on first call to nextToken(). */
75 private int fPrefixLength;
77 // emulate JavaPartitionScanner
78 private boolean fEmulate = false;
80 private int fJavaOffset;
82 private int fJavaLength;
84 private final IToken[] fTokens = new IToken[] {
86 new Token(PHP_SINGLELINE_COMMENT),
87 new Token(PHP_MULTILINE_COMMENT),
88 new Token(PHP_PHPDOC_COMMENT),
89 new Token(PHP_STRING_DQ),
90 new Token(PHP_STRING_SQ),
91 new Token(PHP_STRING_HEREDOC)};
93 public FastJavaPartitionScanner(boolean emulate) {
97 public FastJavaPartitionScanner() {
102 * @see org.eclipse.jface.text.rules.ITokenScanner#nextToken()
104 public IToken nextToken() {
106 // emulate JavaPartitionScanner
108 if (fJavaOffset != -1 && fTokenOffset + fTokenLength != fJavaOffset + fJavaLength) {
109 fTokenOffset += fTokenLength;
117 fTokenOffset += fTokenLength;
118 fTokenLength = fPrefixLength;
121 final int ch = fScanner.read();
125 case ICharacterScanner.EOF:
126 if (fTokenLength > 0) {
127 fLast = NONE; // ignore last
128 return preFix(fState, PHP, NONE, 0);
137 // emulate JavaPartitionScanner
138 if (!fEmulate && fLast != CARRIAGE_RETURN) {
139 fLast = CARRIAGE_RETURN;
146 case SINGLE_LINE_COMMENT:
150 if (fTokenLength > 0) {
151 IToken token = fTokens[fState];
153 // emulate JavaPartitionScanner
159 fLast = CARRIAGE_RETURN;
179 case SINGLE_LINE_COMMENT:
183 // assert(fTokenLength > 0);
184 return postFix(fState);
192 if (fState == SINGLE_LINE_COMMENT) {
193 int nextch = fScanner.read();
195 // <h1>This is an <?php # echo 'simple' ?> example.</h1>
199 return postFix(fState);
205 if (!fEmulate && fLast == CARRIAGE_RETURN) {
207 case SINGLE_LINE_COMMENT:
226 newState = STRING_SQ;
231 newState = STRING_DQ;
235 last = CARRIAGE_RETURN;
250 fLast = NONE; // ignore fLast
251 return preFix(fState, newState, last, 1);
264 if (fTokenLength > 0) {
265 return preFix(PHP, SINGLE_LINE_COMMENT, NONE, 1);
267 preFix(PHP, SINGLE_LINE_COMMENT, NONE, 1);
268 fTokenOffset += fTokenLength;
269 fTokenLength = fPrefixLength;
273 if (fLast == SLASH) {
274 if (fTokenLength - getLastLength(fLast) > 0) {
275 return preFix(PHP, SINGLE_LINE_COMMENT, NONE, 2);
277 preFix(PHP, SINGLE_LINE_COMMENT, NONE, 2);
278 fTokenOffset += fTokenLength;
279 fTokenLength = fPrefixLength;
290 if (fLast == SLASH) {
291 if (fTokenLength - getLastLength(fLast) > 0)
292 return preFix(PHP, MULTI_LINE_COMMENT, SLASH_STAR, 2);
294 preFix(PHP, MULTI_LINE_COMMENT, SLASH_STAR, 2);
295 fTokenOffset += fTokenLength;
296 fTokenLength = fPrefixLength;
306 fLast = NONE; // ignore fLast
307 if (fTokenLength > 0)
308 return preFix(PHP, STRING_SQ, NONE, 1);
310 preFix(PHP, STRING_SQ, NONE, 1);
311 fTokenOffset += fTokenLength;
312 fTokenLength = fPrefixLength;
317 fLast = NONE; // ignore fLast
318 if (fTokenLength > 0)
319 return preFix(PHP, STRING_DQ, NONE, 1);
321 preFix(PHP, STRING_DQ, NONE, 1);
322 fTokenOffset += fTokenLength;
323 fTokenLength = fPrefixLength;
333 case SINGLE_LINE_COMMENT:
341 case SLASH_STAR_STAR:
342 return postFix(MULTI_LINE_COMMENT);
345 return postFix(PHPDOC);
364 case MULTI_LINE_COMMENT:
367 if (fLast == SLASH_STAR) {
368 fLast = SLASH_STAR_STAR;
379 return postFix(MULTI_LINE_COMMENT);
394 fLast = (fLast == BACKSLASH) ? NONE : BACKSLASH;
399 if (fLast != BACKSLASH) {
400 return postFix(STRING_DQ);
415 fLast = (fLast == BACKSLASH) ? NONE : BACKSLASH;
420 if (fLast != BACKSLASH) {
421 return postFix(STRING_SQ);
436 // fLast= (fLast == BACKSLASH) ? NONE : BACKSLASH;
441 // if (fLast != BACKSLASH) {
442 // return postFix(CHARACTER);
458 private static final int getLastLength(int last) {
466 case CARRIAGE_RETURN:
475 case SLASH_STAR_STAR:
480 private final void consume() {
485 private final IToken postFix(int state) {
490 return fTokens[state];
493 private final IToken preFix(int state, int newState, int last, int prefixLength) {
494 // emulate JavaPartitionScanner
495 if (fEmulate && state == PHP && (fTokenLength - getLastLength(fLast) > 0)) {
496 fTokenLength -= getLastLength(fLast);
497 fJavaOffset = fTokenOffset;
498 fJavaLength = fTokenLength;
501 fPrefixLength = prefixLength;
503 return fTokens[state];
506 fTokenLength -= getLastLength(fLast);
508 fPrefixLength = prefixLength;
509 IToken token = fTokens[state];
515 private static int getState(String contentType) {
517 if (contentType == null)
520 else if (contentType.equals(PHP_SINGLELINE_COMMENT))
521 return SINGLE_LINE_COMMENT;
523 else if (contentType.equals(PHP_MULTILINE_COMMENT))
524 return MULTI_LINE_COMMENT;
526 else if (contentType.equals(PHP_PHPDOC_COMMENT))
529 else if (contentType.equals(PHP_STRING_DQ))
532 else if (contentType.equals(PHP_STRING_SQ))
535 else if (contentType.equals(PHP_STRING_HEREDOC))
536 return STRING_HEREDOC;
538 // else if (contentType.equals(JAVA_CHARACTER))
546 * @see IPartitionTokenScanner#setPartialRange(IDocument, int, int, String, int)
548 public void setPartialRange(IDocument document, int offset, int length, String contentType, int partitionOffset) {
549 fScanner.setRange(document, offset, length);
550 setRange(document, offset, length);
551 fTokenOffset = partitionOffset;
553 fPrefixLength = offset - partitionOffset;
556 if (offset == partitionOffset) {
557 // restart at beginning of partition
560 fState = getState(contentType);
563 // emulate JavaPartitionScanner
571 * @see ITokenScanner#setRange(IDocument, int, int)
573 public void setRange(IDocument document, int offset, int length) {
574 fScanner.setRange(document, offset, length);
575 fTokenOffset = offset;
581 // emulate JavaPartitionScanner
589 * @see ITokenScanner#getTokenLength()
591 public int getTokenLength() {
596 * @see ITokenScanner#getTokenOffset()
598 public int getTokenOffset() {
599 if (AbstractPartitioner.DEBUG) {
600 Assert.isTrue(fTokenOffset >= 0, Integer.toString(fTokenOffset));