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;
16 //import org.eclipse.jface.text.Assert;
17 import org.eclipse.core.runtime.Assert;
18 import org.eclipse.jface.text.IDocument;
19 import org.eclipse.jface.text.rules.ICharacterScanner;
20 import org.eclipse.jface.text.rules.IPartitionTokenScanner;
21 import org.eclipse.jface.text.rules.IToken;
22 import org.eclipse.jface.text.rules.Token;
25 * This scanner recognizes the JavaDoc comments, Java multi line comments, Java
26 * single line comments, Java strings.
28 public class FastJavaPartitionScanner implements IPartitionTokenScanner,
32 private static final int PHP = 0;
34 private static final int SINGLE_LINE_COMMENT = 1;
36 private static final int MULTI_LINE_COMMENT = 2;
38 private static final int PHPDOC = 3;
40 private static final int STRING_DQ = 4;
42 private static final int STRING_SQ = 5;
44 private static final int STRING_HEREDOC = 6;
46 // beginning of prefixes and postfixes
47 private static final int NONE = 0;
49 private static final int BACKSLASH = 1; // postfix for STRING_DQ and
52 private static final int SLASH = 2; // prefix for SINGLE_LINE or MULTI_LINE
57 private static final int SLASH_STAR = 3; // prefix for MULTI_LINE_COMMENT
62 private static final int SLASH_STAR_STAR = 4; // prefix for
67 private static final int STAR = 5; // postfix for MULTI_LINE_COMMENT or
71 private static final int CARRIAGE_RETURN = 6; // postfix for STRING_DQ,
74 // SINGLE_LINE_COMMENT
76 // private static final int HEREDOC = 7;
79 private final BufferedDocumentScanner fScanner = new BufferedDocumentScanner(
84 /** The offset of the last returned token. */
85 private int fTokenOffset;
87 /** The length of the last returned token. */
88 private int fTokenLength;
90 /** The state of the scanner. */
93 /** The last significant characters read. */
96 /** The amount of characters already read on first call to nextToken(). */
97 private int fPrefixLength;
99 // emulate JavaPartitionScanner
100 private boolean fEmulate = false;
102 private int fJavaOffset;
104 private int fJavaLength;
106 private final IToken[] fTokens = new IToken[] { new Token(null),
107 new Token(PHP_SINGLELINE_COMMENT),
108 new Token(PHP_MULTILINE_COMMENT), new Token(PHP_PHPDOC_COMMENT),
109 new Token(PHP_STRING_DQ), new Token(PHP_STRING_SQ),
110 new Token(PHP_STRING_HEREDOC) };
112 public FastJavaPartitionScanner(boolean emulate) {
116 public FastJavaPartitionScanner() {
121 * @see org.eclipse.jface.text.rules.ITokenScanner#nextToken()
123 public IToken nextToken() {
125 // emulate JavaPartitionScanner
127 if (fJavaOffset != -1
128 && fTokenOffset + fTokenLength != fJavaOffset + fJavaLength) {
129 fTokenOffset += fTokenLength;
137 fTokenOffset += fTokenLength;
138 fTokenLength = fPrefixLength;
141 final int ch = fScanner.read();
145 case ICharacterScanner.EOF:
146 if (fTokenLength > 0) {
147 fLast = NONE; // ignore last
148 return preFix(fState, PHP, NONE, 0);
157 // emulate JavaPartitionScanner
158 if (!fEmulate && fLast != CARRIAGE_RETURN) {
159 fLast = CARRIAGE_RETURN;
166 case SINGLE_LINE_COMMENT:
170 if (fTokenLength > 0) {
171 IToken token = fTokens[fState];
173 // emulate JavaPartitionScanner
179 fLast = CARRIAGE_RETURN;
199 case SINGLE_LINE_COMMENT:
203 // assert(fTokenLength > 0);
204 return postFix(fState);
212 if (fState == SINGLE_LINE_COMMENT) {
213 int nextch = fScanner.read();
215 // <h1>This is an <?php # echo 'simple' ?> example.</h1>
219 return postFix(fState);
221 // bug #1404228: Crash on <?php // comment ?>
222 if (nextch != ICharacterScanner.EOF) {
229 if (!fEmulate && fLast == CARRIAGE_RETURN) {
231 case SINGLE_LINE_COMMENT:
250 newState = STRING_SQ;
255 newState = STRING_DQ;
259 last = CARRIAGE_RETURN;
274 fLast = NONE; // ignore fLast
275 return preFix(fState, newState, last, 1);
288 if (fTokenLength > 0) {
289 return preFix(PHP, SINGLE_LINE_COMMENT, NONE, 1);
291 preFix(PHP, SINGLE_LINE_COMMENT, NONE, 1);
292 fTokenOffset += fTokenLength;
293 fTokenLength = fPrefixLength;
297 if (fLast == SLASH) {
298 if (fTokenLength - getLastLength(fLast) > 0) {
299 return preFix(PHP, SINGLE_LINE_COMMENT, NONE, 2);
301 preFix(PHP, SINGLE_LINE_COMMENT, NONE, 2);
302 fTokenOffset += fTokenLength;
303 fTokenLength = fPrefixLength;
314 if (fLast == SLASH) {
315 if (fTokenLength - getLastLength(fLast) > 0)
316 return preFix(PHP, MULTI_LINE_COMMENT, SLASH_STAR,
319 preFix(PHP, MULTI_LINE_COMMENT, SLASH_STAR, 2);
320 fTokenOffset += fTokenLength;
321 fTokenLength = fPrefixLength;
331 fLast = NONE; // ignore fLast
332 if (fTokenLength > 0)
333 return preFix(PHP, STRING_SQ, NONE, 1);
335 preFix(PHP, STRING_SQ, NONE, 1);
336 fTokenOffset += fTokenLength;
337 fTokenLength = fPrefixLength;
342 fLast = NONE; // ignore fLast
343 if (fTokenLength > 0)
344 return preFix(PHP, STRING_DQ, NONE, 1);
346 preFix(PHP, STRING_DQ, NONE, 1);
347 fTokenOffset += fTokenLength;
348 fTokenLength = fPrefixLength;
358 case SINGLE_LINE_COMMENT:
366 case SLASH_STAR_STAR:
367 return postFix(MULTI_LINE_COMMENT);
370 return postFix(PHPDOC);
389 case MULTI_LINE_COMMENT:
392 if (fLast == SLASH_STAR) {
393 fLast = SLASH_STAR_STAR;
404 return postFix(MULTI_LINE_COMMENT);
419 fLast = (fLast == BACKSLASH) ? NONE : BACKSLASH;
424 if (fLast != BACKSLASH) {
425 return postFix(STRING_DQ);
440 fLast = (fLast == BACKSLASH) ? NONE : BACKSLASH;
445 if (fLast != BACKSLASH) {
446 return postFix(STRING_SQ);
461 // fLast= (fLast == BACKSLASH) ? NONE : BACKSLASH;
466 // if (fLast != BACKSLASH) {
467 // return postFix(CHARACTER);
483 private static final int getLastLength(int last) {
491 case CARRIAGE_RETURN:
500 case SLASH_STAR_STAR:
505 private final void consume() {
510 private final IToken postFix(int state) {
515 return fTokens[state];
518 private final IToken preFix(int state, int newState, int last,
520 // emulate JavaPartitionScanner
521 if (fEmulate && state == PHP
522 && (fTokenLength - getLastLength(fLast) > 0)) {
523 fTokenLength -= getLastLength(fLast);
524 fJavaOffset = fTokenOffset;
525 fJavaLength = fTokenLength;
528 fPrefixLength = prefixLength;
530 return fTokens[state];
533 fTokenLength -= getLastLength(fLast);
535 fPrefixLength = prefixLength;
536 IToken token = fTokens[state];
542 private static int getState(String contentType) {
544 if (contentType == null)
547 else if (contentType.equals(PHP_SINGLELINE_COMMENT))
548 return SINGLE_LINE_COMMENT;
550 else if (contentType.equals(PHP_MULTILINE_COMMENT))
551 return MULTI_LINE_COMMENT;
553 else if (contentType.equals(PHP_PHPDOC_COMMENT))
556 else if (contentType.equals(PHP_STRING_DQ))
559 else if (contentType.equals(PHP_STRING_SQ))
562 else if (contentType.equals(PHP_STRING_HEREDOC))
563 return STRING_HEREDOC;
565 // else if (contentType.equals(JAVA_CHARACTER))
573 * @see IPartitionTokenScanner#setPartialRange(IDocument, int, int, String,
576 public void setPartialRange(IDocument document, int offset, int length,
577 String contentType, int partitionOffset) {
578 fScanner.setRange(document, offset, length);
579 setRange(document, offset, length);
580 fTokenOffset = partitionOffset;
582 fPrefixLength = offset - partitionOffset;
585 if (offset == partitionOffset) {
586 // restart at beginning of partition
589 fState = getState(contentType);
592 // emulate JavaPartitionScanner
600 * @see ITokenScanner#setRange(IDocument, int, int)
602 public void setRange(IDocument document, int offset, int length) {
603 fScanner.setRange(document, offset, length);
604 fTokenOffset = offset;
610 // emulate JavaPartitionScanner
618 * @see ITokenScanner#getTokenLength()
620 public int getTokenLength() {
625 * @see ITokenScanner#getTokenOffset()
627 public int getTokenOffset() {
628 if (AbstractPartitioner.DEBUG) {
629 Assert.isTrue(fTokenOffset >= 0, Integer.toString(fTokenOffset));