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.RuleBasedPartitionScanner;
21 import org.eclipse.jface.text.rules.Token;
24 * This scanner recognizes the JavaDoc comments, Java multi line comments, Java single line comments, Java strings.
26 public class FastJavaPartitionScanner implements IPartitionTokenScanner, IPHPPartitions {
29 private static final int PHP = 0;
31 private static final int SINGLE_LINE_COMMENT = 1;
33 private static final int MULTI_LINE_COMMENT = 2;
35 private static final int PHPDOC = 3;
37 private static final int STRING_DQ = 4;
39 private static final int STRING_SQ = 5;
41 // private static final int CHARACTER= 4;
43 // beginning of prefixes and postfixes
44 private static final int NONE = 0;
46 private static final int BACKSLASH = 1; // postfix for STRING and CHARACTER
48 private static final int SLASH = 2; // prefix for SINGLE_LINE or MULTI_LINE or JAVADOC
50 private static final int SLASH_STAR = 3; // prefix for MULTI_LINE_COMMENT or JAVADOC
52 private static final int SLASH_STAR_STAR = 4; // prefix for MULTI_LINE_COMMENT or JAVADOC
54 private static final int STAR = 5; // postfix for MULTI_LINE_COMMENT or JAVADOC
56 private static final int CARRIAGE_RETURN = 6; // postfix for STRING, CHARACTER and SINGLE_LINE_COMMENT
59 private final BufferedDocumentScanner fScanner = new BufferedDocumentScanner(1000); // faster implementation
61 /** The offset of the last returned token. */
62 private int fTokenOffset;
64 /** The length of the last returned token. */
65 private int fTokenLength;
67 /** The state of the scanner. */
70 /** The last significant characters read. */
73 /** The amount of characters already read on first call to nextToken(). */
74 private int fPrefixLength;
76 // emulate JavaPartitionScanner
77 private boolean fEmulate = false;
79 private int fJavaOffset;
81 private int fJavaLength;
83 private final IToken[] fTokens = new IToken[] { new Token(null), new Token(PHP_SINGLELINE_COMMENT),
84 new Token(PHP_MULTILINE_COMMENT), new Token(PHP_PHPDOC_COMMENT), new Token(PHP_STRING_DQ), new Token(PHP_STRING_SQ) };
86 public FastJavaPartitionScanner(boolean emulate) {
90 public FastJavaPartitionScanner() {
95 * @see org.eclipse.jface.text.rules.ITokenScanner#nextToken()
97 public IToken nextToken() {
99 // emulate JavaPartitionScanner
101 if (fJavaOffset != -1 && fTokenOffset + fTokenLength != fJavaOffset + fJavaLength) {
102 fTokenOffset += fTokenLength;
110 fTokenOffset += fTokenLength;
111 fTokenLength = fPrefixLength;
114 final int ch = fScanner.read();
118 case ICharacterScanner.EOF:
119 if (fTokenLength > 0) {
120 fLast = NONE; // ignore last
121 return preFix(fState, PHP, NONE, 0);
130 // emulate JavaPartitionScanner
131 if (!fEmulate && fLast != CARRIAGE_RETURN) {
132 fLast = CARRIAGE_RETURN;
139 case SINGLE_LINE_COMMENT:
143 if (fTokenLength > 0) {
144 IToken token = fTokens[fState];
146 // emulate JavaPartitionScanner
152 fLast = CARRIAGE_RETURN;
172 case SINGLE_LINE_COMMENT:
176 // assert(fTokenLength > 0);
177 return postFix(fState);
185 if (!fEmulate && fLast == CARRIAGE_RETURN) {
187 case SINGLE_LINE_COMMENT:
206 newState = STRING_SQ;
211 newState = STRING_DQ;
215 last = CARRIAGE_RETURN;
230 fLast = NONE; // ignore fLast
231 return preFix(fState, newState, last, 1);
244 if (fTokenLength > 0) {
245 return preFix(PHP, SINGLE_LINE_COMMENT, NONE, 1);
247 preFix(PHP, SINGLE_LINE_COMMENT, NONE, 1);
248 fTokenOffset += fTokenLength;
249 fTokenLength = fPrefixLength;
253 if (fLast == SLASH) {
254 if (fTokenLength - getLastLength(fLast) > 0) {
255 return preFix(PHP, SINGLE_LINE_COMMENT, NONE, 2);
257 preFix(PHP, SINGLE_LINE_COMMENT, NONE, 2);
258 fTokenOffset += fTokenLength;
259 fTokenLength = fPrefixLength;
270 if (fLast == SLASH) {
271 if (fTokenLength - getLastLength(fLast) > 0)
272 return preFix(PHP, MULTI_LINE_COMMENT, SLASH_STAR, 2);
274 preFix(PHP, MULTI_LINE_COMMENT, SLASH_STAR, 2);
275 fTokenOffset += fTokenLength;
276 fTokenLength = fPrefixLength;
286 fLast = NONE; // ignore fLast
287 if (fTokenLength > 0)
288 return preFix(PHP, STRING_SQ, NONE, 1);
290 preFix(PHP, STRING_SQ, NONE, 1);
291 fTokenOffset += fTokenLength;
292 fTokenLength = fPrefixLength;
297 fLast = NONE; // ignore fLast
298 if (fTokenLength > 0)
299 return preFix(PHP, STRING_DQ, NONE, 1);
301 preFix(PHP, STRING_DQ, NONE, 1);
302 fTokenOffset += fTokenLength;
303 fTokenLength = fPrefixLength;
313 case SINGLE_LINE_COMMENT:
321 case SLASH_STAR_STAR:
322 return postFix(MULTI_LINE_COMMENT);
325 return postFix(PHPDOC);
344 case MULTI_LINE_COMMENT:
347 if (fLast == SLASH_STAR) {
348 fLast = SLASH_STAR_STAR;
359 return postFix(MULTI_LINE_COMMENT);
374 fLast = (fLast == BACKSLASH) ? NONE : BACKSLASH;
379 if (fLast != BACKSLASH) {
380 return postFix(STRING_DQ);
395 fLast = (fLast == BACKSLASH) ? NONE : BACKSLASH;
400 if (fLast != BACKSLASH) {
401 return postFix(STRING_SQ);
416 // fLast= (fLast == BACKSLASH) ? NONE : BACKSLASH;
421 // if (fLast != BACKSLASH) {
422 // return postFix(CHARACTER);
438 private static final int getLastLength(int last) {
446 case CARRIAGE_RETURN:
455 case SLASH_STAR_STAR:
460 private final void consume() {
465 private final IToken postFix(int state) {
470 return fTokens[state];
473 private final IToken preFix(int state, int newState, int last, int prefixLength) {
474 // emulate JavaPartitionScanner
475 if (fEmulate && state == PHP && (fTokenLength - getLastLength(fLast) > 0)) {
476 fTokenLength -= getLastLength(fLast);
477 fJavaOffset = fTokenOffset;
478 fJavaLength = fTokenLength;
481 fPrefixLength = prefixLength;
483 return fTokens[state];
486 fTokenLength -= getLastLength(fLast);
488 fPrefixLength = prefixLength;
489 IToken token = fTokens[state];
495 private static int getState(String contentType) {
497 if (contentType == null)
500 else if (contentType.equals(PHP_SINGLELINE_COMMENT))
501 return SINGLE_LINE_COMMENT;
503 else if (contentType.equals(PHP_MULTILINE_COMMENT))
504 return MULTI_LINE_COMMENT;
506 else if (contentType.equals(PHP_PHPDOC_COMMENT))
509 else if (contentType.equals(PHP_STRING_DQ))
511 else if (contentType.equals(PHP_STRING_SQ))
513 // else if (contentType.equals(JAVA_CHARACTER))
521 * @see IPartitionTokenScanner#setPartialRange(IDocument, int, int, String, int)
523 public void setPartialRange(IDocument document, int offset, int length, String contentType, int partitionOffset) {
524 fScanner.setRange(document, offset, length);
525 setRange(document, offset, length);
526 fTokenOffset = partitionOffset;
528 fPrefixLength = offset - partitionOffset;
531 if (offset == partitionOffset) {
532 // restart at beginning of partition
535 fState = getState(contentType);
538 // emulate JavaPartitionScanner
546 * @see ITokenScanner#setRange(IDocument, int, int)
548 public void setRange(IDocument document, int offset, int length) {
549 fScanner.setRange(document, offset, length);
550 fTokenOffset = offset;
556 // emulate JavaPartitionScanner
564 * @see ITokenScanner#getTokenLength()
566 public int getTokenLength() {
571 * @see ITokenScanner#getTokenOffset()
573 public int getTokenOffset() {
574 if (AbstractPartitioner.DEBUG) {
575 Assert.isTrue(fTokenOffset >= 0, Integer.toString(fTokenOffset));