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
24 * single line comments, Java strings.
26 public class FastJavaPartitionScanner implements IPartitionTokenScanner,
30 private static final int PHP = 0;
32 private static final int SINGLE_LINE_COMMENT = 1;
34 private static final int MULTI_LINE_COMMENT = 2;
36 private static final int PHPDOC = 3;
38 private static final int STRING_DQ = 4;
40 private static final int STRING_SQ = 5;
42 private static final int STRING_HEREDOC = 6;
44 // beginning of prefixes and postfixes
45 private static final int NONE = 0;
47 private static final int BACKSLASH = 1; // postfix for STRING_DQ and
50 private static final int SLASH = 2; // prefix for SINGLE_LINE or MULTI_LINE
55 private static final int SLASH_STAR = 3; // prefix for MULTI_LINE_COMMENT
60 private static final int SLASH_STAR_STAR = 4; // prefix for
65 private static final int STAR = 5; // postfix for MULTI_LINE_COMMENT or
69 private static final int CARRIAGE_RETURN = 6; // postfix for STRING_DQ,
72 // SINGLE_LINE_COMMENT
74 // private static final int HEREDOC = 7;
77 private final BufferedDocumentScanner fScanner = new BufferedDocumentScanner(
82 /** The offset of the last returned token. */
83 private int fTokenOffset;
85 /** The length of the last returned token. */
86 private int fTokenLength;
88 /** The state of the scanner. */
91 /** The last significant characters read. */
94 /** The amount of characters already read on first call to nextToken(). */
95 private int fPrefixLength;
97 // emulate JavaPartitionScanner
98 private boolean fEmulate = false;
100 private int fJavaOffset;
102 private int fJavaLength;
104 private final IToken[] fTokens = new IToken[] { new Token(null),
105 new Token(PHP_SINGLELINE_COMMENT),
106 new Token(PHP_MULTILINE_COMMENT), new Token(PHP_PHPDOC_COMMENT),
107 new Token(PHP_STRING_DQ), new Token(PHP_STRING_SQ),
108 new Token(PHP_STRING_HEREDOC) };
110 public FastJavaPartitionScanner(boolean emulate) {
114 public FastJavaPartitionScanner() {
119 * @see org.eclipse.jface.text.rules.ITokenScanner#nextToken()
121 public IToken nextToken() {
123 // emulate JavaPartitionScanner
125 if (fJavaOffset != -1
126 && fTokenOffset + fTokenLength != fJavaOffset + fJavaLength) {
127 fTokenOffset += fTokenLength;
135 fTokenOffset += fTokenLength;
136 fTokenLength = fPrefixLength;
139 final int ch = fScanner.read();
143 case ICharacterScanner.EOF:
144 if (fTokenLength > 0) {
145 fLast = NONE; // ignore last
146 return preFix(fState, PHP, NONE, 0);
155 // emulate JavaPartitionScanner
156 if (!fEmulate && fLast != CARRIAGE_RETURN) {
157 fLast = CARRIAGE_RETURN;
164 case SINGLE_LINE_COMMENT:
168 if (fTokenLength > 0) {
169 IToken token = fTokens[fState];
171 // emulate JavaPartitionScanner
177 fLast = CARRIAGE_RETURN;
197 case SINGLE_LINE_COMMENT:
201 // assert(fTokenLength > 0);
202 return postFix(fState);
210 if (fState == SINGLE_LINE_COMMENT) {
211 int nextch = fScanner.read();
213 // <h1>This is an <?php # echo 'simple' ?> example.</h1>
217 return postFix(fState);
219 // bug #1404228: Crash on <?php // comment ?>
220 if (nextch != ICharacterScanner.EOF) {
227 if (!fEmulate && fLast == CARRIAGE_RETURN) {
229 case SINGLE_LINE_COMMENT:
248 newState = STRING_SQ;
253 newState = STRING_DQ;
257 last = CARRIAGE_RETURN;
272 fLast = NONE; // ignore fLast
273 return preFix(fState, newState, last, 1);
286 if (fTokenLength > 0) {
287 return preFix(PHP, SINGLE_LINE_COMMENT, NONE, 1);
289 preFix(PHP, SINGLE_LINE_COMMENT, NONE, 1);
290 fTokenOffset += fTokenLength;
291 fTokenLength = fPrefixLength;
295 if (fLast == SLASH) {
296 if (fTokenLength - getLastLength(fLast) > 0) {
297 return preFix(PHP, SINGLE_LINE_COMMENT, NONE, 2);
299 preFix(PHP, SINGLE_LINE_COMMENT, NONE, 2);
300 fTokenOffset += fTokenLength;
301 fTokenLength = fPrefixLength;
312 if (fLast == SLASH) {
313 if (fTokenLength - getLastLength(fLast) > 0)
314 return preFix(PHP, MULTI_LINE_COMMENT, SLASH_STAR,
317 preFix(PHP, MULTI_LINE_COMMENT, SLASH_STAR, 2);
318 fTokenOffset += fTokenLength;
319 fTokenLength = fPrefixLength;
329 fLast = NONE; // ignore fLast
330 if (fTokenLength > 0)
331 return preFix(PHP, STRING_SQ, NONE, 1);
333 preFix(PHP, STRING_SQ, NONE, 1);
334 fTokenOffset += fTokenLength;
335 fTokenLength = fPrefixLength;
340 fLast = NONE; // ignore fLast
341 if (fTokenLength > 0)
342 return preFix(PHP, STRING_DQ, NONE, 1);
344 preFix(PHP, STRING_DQ, NONE, 1);
345 fTokenOffset += fTokenLength;
346 fTokenLength = fPrefixLength;
356 case SINGLE_LINE_COMMENT:
364 case SLASH_STAR_STAR:
365 return postFix(MULTI_LINE_COMMENT);
368 return postFix(PHPDOC);
387 case MULTI_LINE_COMMENT:
390 if (fLast == SLASH_STAR) {
391 fLast = SLASH_STAR_STAR;
402 return postFix(MULTI_LINE_COMMENT);
417 fLast = (fLast == BACKSLASH) ? NONE : BACKSLASH;
422 if (fLast != BACKSLASH) {
423 return postFix(STRING_DQ);
438 fLast = (fLast == BACKSLASH) ? NONE : BACKSLASH;
443 if (fLast != BACKSLASH) {
444 return postFix(STRING_SQ);
459 // fLast= (fLast == BACKSLASH) ? NONE : BACKSLASH;
464 // if (fLast != BACKSLASH) {
465 // return postFix(CHARACTER);
481 private static final int getLastLength(int last) {
489 case CARRIAGE_RETURN:
498 case SLASH_STAR_STAR:
503 private final void consume() {
508 private final IToken postFix(int state) {
513 return fTokens[state];
516 private final IToken preFix(int state, int newState, int last,
518 // emulate JavaPartitionScanner
519 if (fEmulate && state == PHP
520 && (fTokenLength - getLastLength(fLast) > 0)) {
521 fTokenLength -= getLastLength(fLast);
522 fJavaOffset = fTokenOffset;
523 fJavaLength = fTokenLength;
526 fPrefixLength = prefixLength;
528 return fTokens[state];
531 fTokenLength -= getLastLength(fLast);
533 fPrefixLength = prefixLength;
534 IToken token = fTokens[state];
540 private static int getState(String contentType) {
542 if (contentType == null)
545 else if (contentType.equals(PHP_SINGLELINE_COMMENT))
546 return SINGLE_LINE_COMMENT;
548 else if (contentType.equals(PHP_MULTILINE_COMMENT))
549 return MULTI_LINE_COMMENT;
551 else if (contentType.equals(PHP_PHPDOC_COMMENT))
554 else if (contentType.equals(PHP_STRING_DQ))
557 else if (contentType.equals(PHP_STRING_SQ))
560 else if (contentType.equals(PHP_STRING_HEREDOC))
561 return STRING_HEREDOC;
563 // else if (contentType.equals(JAVA_CHARACTER))
571 * @see IPartitionTokenScanner#setPartialRange(IDocument, int, int, String,
574 public void setPartialRange(IDocument document, int offset, int length,
575 String contentType, int partitionOffset) {
576 fScanner.setRange(document, offset, length);
577 setRange(document, offset, length);
578 fTokenOffset = partitionOffset;
580 fPrefixLength = offset - partitionOffset;
583 if (offset == partitionOffset) {
584 // restart at beginning of partition
587 fState = getState(contentType);
590 // emulate JavaPartitionScanner
598 * @see ITokenScanner#setRange(IDocument, int, int)
600 public void setRange(IDocument document, int offset, int length) {
601 fScanner.setRange(document, offset, length);
602 fTokenOffset = offset;
608 // emulate JavaPartitionScanner
616 * @see ITokenScanner#getTokenLength()
618 public int getTokenLength() {
623 * @see ITokenScanner#getTokenOffset()
625 public int getTokenOffset() {
626 if (AbstractPartitioner.DEBUG) {
627 Assert.isTrue(fTokenOffset >= 0, Integer.toString(fTokenOffset));