Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
Copyright (c) 2000, 2011 IBM Corporation and others. All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse Public License v1.0 which accompanies this distribution, and is available at http://www.eclipse.org/legal/epl-v10.html Contributors: IBM Corporation - initial API and implementation /
 
 package org.eclipse.jdt.internal.codeassist.complete;
 
 /*
  * Scanner aware of a cursor location so as to discard trailing portions of identifiers
  * containing the cursor location.
  *
  * Cursor location denotes the position of the last character behind which completion
  * got requested:
  *  -1 means completion at the very beginning of the source
  *	0  means completion behind the first character
  *  n  means completion behind the n-th character
  */
 
 public class CompletionScanner extends Scanner {
 
 	public char[] completionIdentifier;
 	public int cursorLocation;
 	public int endOfEmptyToken = -1;
 
 	/* Source positions of the completedIdentifier
 	 * if inside actual identifier, end goes to the actual identifier
 	 * end, in other words, beyond cursor location
 	 */
 	public int completedIdentifierStart = 0;
 	public int completedIdentifierEnd = -1;
 	public int unicodeCharSize;
 
 	public static final char[] EmptyCompletionIdentifier = {};
 
 public CompletionScanner(long sourceLevel) {
 	super(
 		false /*comment*/,
 		false /*whitespace*/,
 		false /*nls*/,
 		sourceLevel,
 		null /*taskTags*/,
 		null/*taskPriorities*/,
 		true/*taskCaseSensitive*/);
 }
 /*
  * Truncate the current identifier if it is containing the cursor location. Since completion is performed
  * on an identifier prefix.
  *
  */
 public char[] getCurrentIdentifierSource() {
 
 	if (this. == null){
 		if (this. < this. && this. == this.){ // fake empty identifier got issued
 			// remember actual identifier positions
 		}
 		if (this.+1 >= this. && this. < this.){
 			// remember actual identifier positions
 			if (this. != 0){			// check unicode scenario
 				int length = this. + 1 - this. - this.;
 				System.arraycopy(this., 1, this. = new char[length], 0, length);
 			} else {
 				// no char[] sharing around completionIdentifier, we want it to be unique so as to use identity checks
 				int length = this. + 1 - this.;
 				System.arraycopy(this.this., (this. = new char[length]), 0, length);
 			}
 			return this.;
 		}
 	}
 	return super.getCurrentIdentifierSource();
 }
 
 public char[] getCurrentTokenSourceString() {
 	if (this. == null){
 		if (this.+1 >= this. && this. < this.){
 			// remember actual identifier positions
 			if (this. != 0){			// check unicode scenario
 				int length = this. - this. - this.;
 				System.arraycopy(this., 2, this. = new char[length], 0, length);
 			} else {
 				// no char[] sharing around completionIdentifier, we want it to be unique so as to use identity checks
 				int length = this. - this.;
 				System.arraycopy(this.this. + 1, (this. = new char[length]), 0, length);
 			}
		}
	}
public int getNextToken() throws InvalidInputException {
	this. = false;
	this. = 0;
	if (this.) {
		this. = false;
	}
	int whiteStart = 0;
	try {
		while (true) { //loop for jumping over comments
			//start with a new token (even comment written with unicode )
			// ---------Consume white space and handles start position---------
			whiteStart = this.;
			boolean isWhiteSpacehasWhiteSpaces = false;
			int offset = 0;
			do {
				boolean checkIfUnicode = false;
				try {
					checkIfUnicode = ((this. = this.[this.++]) == '\\')
						&& (this.[this.] == 'u');
					if (this. && (whiteStart != this. - 1)) {
						// reposition scanner in case we are interested by spaces as tokens
						this. = whiteStart;
					}
					if (this. > this.) {
						/* might be completing at eof (e.g. behind a dot) */
						if (this. == null &&
							this. == this. + 1){
							this. = this.// for being detected as empty free identifier
						}
						return ;
					}
				}
				if (checkIfUnicode) {
					isWhiteSpace = jumpOverUnicodeWhiteSpace();
					offset = 6;
else {
					offset = 1;
					if ((this. == '\r') || (this. == '\n')) {
						//checkNonExternalizedString();
						if (this.) {
						}
					}
					isWhiteSpace =
						(this. == ' ') || CharOperation.isWhitespace(this.);
				}
				if (isWhiteSpace) {
					hasWhiteSpaces = true;
				}
				/* completion requesting strictly inside blanks */
				if ((whiteStart != this.)
					//&& (previousToken == TokenNameDOT)
					&& (this. == null)
					&& (whiteStart <= this.+1)
					&& (this. < this.)
					&& !ScannerHelper.isJavaIdentifierStart(this.this.)){
					this. = this.// for next token read
				}
while (isWhiteSpace);
			if (this. && hasWhiteSpaces) {
				// reposition scanner in case we are interested by spaces as tokens
				this.-=offset;
				this. = whiteStart;
			}
			//little trick to get out in the middle of a source computation
			if (this. > this.){
				/* might be completing at eof (e.g. behind a dot) */
				if (this. == null &&
					this. == this. + 1){
					// compute end of empty identifier.
					// if the empty identifier is at the start of a next token the end of
					// empty identifier is the end of the next token (e.g. "<empty token>next").
					int temp = this.;
					this. = this..length;
				 	while(getNextCharAsJavaIdentifierPart()){/*empty*/}
				 	this. = temp;
				 	this. = this. - 1;
					this. = this.// for being detected as empty free identifier
				}
				return ;
			}
			// ---------Identify the next token-------------
			switch (this.) {
				case '@' :
					return ;
				case '(' :
				case ')' :
				case '{' :
				case '}' :
				case '[' :
				case ']' :
				case ';' :
				case ',' :
				case '.' :
					if (this. <= this.
							&& this. < this.){
						return // completion inside .<|>12
					}
						return scanNumber(true);
					}
					int temp = this.;
					if (getNextChar('.')) {
						if (getNextChar('.')) {
else {
							this. = temp;
							return ;
						}
else {
						this. = temp;
						return ;
					}
				case '+' :
					{
						int test;
						if ((test = getNextChar('+''=')) == 0)
						if (test > 0)
					}
				case '-' :
					{
						int test;
						if ((test = getNextChar('-''=')) == 0)
						if (test > 0)
					}
				case '~' :
				case '!' :
					if (getNextChar('='))
					return ;
				case '*' :
					if (getNextChar('='))
				case '%' :
					if (getNextChar('='))
				case '<' :
					{
						int test;
						if ((test = getNextChar('=''<')) == 0)
						if (test > 0) {
							if (getNextChar('='))
						}
					}
				case '>' :
					{
						int test;
						if (this.) {
						}
						if ((test = getNextChar('=''>')) == 0)
						if (test > 0) {
							if ((test = getNextChar('=''>')) == 0)
							if (test > 0) {
								if (getNextChar('='))
							}
						}
					}
				case '=' :
					if (getNextChar('='))
				case '&' :
					{
						int test;
						if ((test = getNextChar('&''=')) == 0)
						if (test > 0)
						return ;
					}
				case '|' :
					{
						int test;
						if ((test = getNextChar('|''=')) == 0)
						if (test > 0)
						return ;
					}
				case '^' :
					if (getNextChar('='))
					return ;
				case '?' :
				case ':' :
				case '\'' :
					{
						int test;
						if ((test = getNextChar('\n''\r')) == 0) {
						}
						if (test > 0) {
							// relocate if finding another quote fairly close: thus unicode '/u000D' will be fully consumed
							for (int lookAhead = 0; lookAhead < 3; lookAhead++) {
								if (this. + lookAhead == this.)
									break;
								if (this.[this. + lookAhead] == '\n')
									break;
								if (this.[this. + lookAhead] == '\'') {
									this. += lookAhead + 1;
									break;
								}
							}
						}
					}
					if (getNextChar('\'')) {
						// relocate if finding another quote fairly close: thus unicode '/u000D' will be fully consumed
						for (int lookAhead = 0; lookAhead < 3; lookAhead++) {
							if (this. + lookAhead == this.)
								break;
							if (this.[this. + lookAhead] == '\n')
								break;
							if (this.[this. + lookAhead] == '\'') {
								this. += lookAhead + 1;
								break;
							}
						}
					}
					if (getNextChar('\\')) {
						if (this.) {
							// consume next character
							this. = false;
							if (((this. = this.[this.++]) == '\\') && (this.[this.] == 'u')) {
else {
								if (this. != 0) {
								}
							}
else {
						}
else { // consume next character
						this. = false;
						boolean checkIfUnicode = false;
						try {
							checkIfUnicode = ((this. = this.[this.++]) == '\\')
							&& (this.[this.] == 'u');
						}
						if (checkIfUnicode) {
else {
							if (this. != 0) {
							    unicodeStore();
							}
						}
					}
					if (getNextChar('\''))
					// relocate if finding another quote fairly close: thus unicode '/u000D' will be fully consumed
					for (int lookAhead = 0; lookAhead < 20; lookAhead++) {
						if (this. + lookAhead == this.)
							break;
						if (this.[this. + lookAhead] == '\n')
							break;
						if (this.[this. + lookAhead] == '\'') {
							this. += lookAhead + 1;
							break;
						}
					}
				case '"' :
					try {
						// consume next character
						this. = false;
						boolean isUnicode = false;
						if (((this. = this.[this.++]) == '\\')
							&& (this.[this.] == 'u')) {
							isUnicode = true;
else {
							if (this. != 0) {
							    unicodeStore();
							}
						}
						while (this. != '"') {
\r and \n are not valid in string literals **
							if ((this. == '\n') || (this. == '\r')) {
								if (isUnicode) {
									int start = this. - 5;
									while(this.[start] != '\\') {
										start--;
									}
									if(this. <= this.
											&& this. <= this.-1) {
										this. = start;
										// complete inside a string literal
									}
									start = this.;
									for (int lookAhead = 0; lookAhead < 50; lookAhead++) {
										if (this. >= this.) {
											this. = start;
											break;
										}
										if (((this. = this.[this.++]) == '\\') && (this.[this.] == 'u')) {
											isUnicode = true;
else {
											isUnicode = false;
										}
										if (!isUnicode && this. == '\n') {
											this.--; // set current position on new line character
											break;
										}
										if (this. == '\"') {
										}
									}
else {
									this.--; // set current position on new line character
									if(this. <= this.
											&& this. <= this.-1) {
										// complete inside a string literal
									}
								}
							}
							if (this. == '\\') {
								if (this.) {
									// consume next character
									this. = false;
									if (((this. = this.[this.++]) == '\\') && (this.[this.] == 'u')) {
										isUnicode = true;
else {
										isUnicode = false;
									}
else {
									if (this. == 0) {
									}
								}
								// we need to compute the escape character in a separate buffer
								if (this. != 0) {
								}
							}
							// consume next character
							this. = false;
							if (((this. = this.[this.++]) == '\\')
								&& (this.[this.] == 'u')) {
								isUnicode = true;
else {
								isUnicode = false;
								if (this. != 0) {
								    unicodeStore();
								}
							}
						}
catch (IndexOutOfBoundsException e) {
						if(this. <= this.
							&& this. < this.) {
							// complete inside a string literal
						}
catch (InvalidInputException e) {
							// relocate if finding another quote fairly close: thus unicode '/u000D' will be fully consumed
							for (int lookAhead = 0; lookAhead < 50; lookAhead++) {
								if (this. + lookAhead == this.)
									break;
								if (this.[this. + lookAhead] == '\n')
									break;
								if (this.[this. + lookAhead] == '\"') {
									this. += lookAhead + 1;
									break;
								}
							}
						}
						throw e// rethrow
					}
				case '/' :
					{
						int test;
						if ((test = getNextChar('/''*')) == 0) { //line comment
							try { //get the next char
								if (((this. = this.[this.++]) == '\\')
									&& (this.[this.] == 'u')) {
									//-------------unicode traitement ------------
									int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
									while (this.[this.] == 'u') {
									}
									if ((c1 = ScannerHelper.getHexadecimalValue(this.[this.++])) > 15
										|| c1 < 0
										|| (c2 = ScannerHelper.getHexadecimalValue(this.[this.++])) > 15
										|| c2 < 0
										|| (c3 = ScannerHelper.getHexadecimalValue(this.[this.++])) > 15
										|| c3 < 0
										|| (c4 = ScannerHelper.getHexadecimalValue(this.[this.++])) > 15
										|| c4 < 0) {
else {
										this. = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
									}
								}
								//handle the \\u case manually into comment
								if (this. == '\\') {
									if (this.[this.] == '\\')
//jump over the \\
								boolean isUnicode = false;
								while (this. != '\r' && this. != '\n') {
									//get the next char
									isUnicode = false;
									if (((this. = this.[this.++]) == '\\')
										&& (this.[this.] == 'u')) {
										isUnicode = true;
										//-------------unicode traitement ------------
										int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
										while (this.[this.] == 'u') {
										}
										if ((c1 = ScannerHelper.getHexadecimalValue(this.[this.++])) > 15
											|| c1 < 0
											|| (c2 = ScannerHelper.getHexadecimalValue(this.[this.++])) > 15
											|| c2 < 0
											|| (c3 = ScannerHelper.getHexadecimalValue(this.[this.++])) > 15
											|| c3 < 0
											|| (c4 = ScannerHelper.getHexadecimalValue(this.[this.++])) > 15
											|| c4 < 0) {
else {
											this. = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
										}
									}
									//handle the \\u case manually into comment
									if (this. == '\\') {
										if (this.[this.] == '\\')
//jump over the \\
								}
								/*
								 * We need to completely consume the line break
								 */
								if (this. == '\r'
								   && this. > this.) {
								   	if (this.[this.] == '\n') {
										this. = '\n';
								   	} else if ((this.[this.] == '\\')
										&& (this.[this. + 1] == 'u')) {
										isUnicode = true;
										char unicodeChar;
										int index = this. + 1;
										index++;
										while (this.[index] == 'u') {
											index++;
										}
										//-------------unicode traitement ------------
										int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
										if ((c1 = ScannerHelper.getHexadecimalValue(this.[index++])) > 15
											|| c1 < 0
											|| (c2 = ScannerHelper.getHexadecimalValue(this.[index++])) > 15
											|| c2 < 0
											|| (c3 = ScannerHelper.getHexadecimalValue(this.[index++])) > 15
											|| c3 < 0
											|| (c4 = ScannerHelper.getHexadecimalValue(this.[index++])) > 15
											|| c4 < 0) {
											this. = index;
else {
											unicodeChar = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
										}
										if (unicodeChar == '\n') {
											this. = index;
											this. = '\n';
										}
									}
							   	}
								if (this. <= this. && this. < this.-1){
								}
								if (this. != nullcheckTaskTag(this.this.);
								if ((this. == '\r') || (this. == '\n')) {
									//checkNonExternalizedString();
									if (this.) {
										if (isUnicode) {
else {
										}
									}
								}
								if (this.) {
								}
catch (IndexOutOfBoundsException e) {
								if (this. != nullcheckTaskTag(this.this.);
								if (this.) {
else {
								}
							}
							break;
						}
						if (test > 0) { //traditional and javadoc comment
							try { //get the next char
								boolean isJavadoc = falsestar = false;
								boolean isUnicode = false;
								int previous;
								// consume next character
								this. = false;
								if (((this. = this.[this.++]) == '\\')
									&& (this.[this.] == 'u')) {
									isUnicode = true;
else {
									isUnicode = false;
									if (this. != 0) {
									    unicodeStore();
									}
								}
								if (this. == '*') {
									isJavadoc = true;
									star = true;
								}
								if ((this. == '\r') || (this. == '\n')) {
									//checkNonExternalizedString();
									if (this.) {
										if (!isUnicode) {
										}
									}
								}
								isUnicode = false;
								previous = this.;
								if (((this. = this.[this.++]) == '\\')
									&& (this.[this.] == 'u')) {
									//-------------unicode traitement ------------
									isUnicode = true;
else {
									isUnicode = false;
								}
								//handle the \\u case manually into comment
								if (this. == '\\') {
									if (this.[this.] == '\\')
//jump over the \\
								// empty comment is not a javadoc /**/
								if (this. == '/') {
									isJavadoc = false;
								}
								//loop until end of comment */
								int firstTag = 0;
								while ((this. != '/') || (!star)) {
									if ((this. == '\r') || (this. == '\n')) {
										//checkNonExternalizedString();
										if (this.) {
											if (!isUnicode) {
											}
										}
									}									
									switch (this.) {
										case '*':
											star = true;
											break;
										case '@':
											if (firstTag == 0 && this.isFirstTag()) {
												firstTag = previous;
											}
											//$FALL-THROUGH$ default case to set star to false
										default:
											star = false;
									}
 									//get next char
									previous = this.;
									if (((this. = this.[this.++]) == '\\')
										&& (this.[this.] == 'u')) {
										//-------------unicode traitement ------------
										isUnicode = true;
else {
										isUnicode = false;
									}
									//handle the \\u case manually into comment
									if (this. == '\\') {
										if (this.[this.] == '\\')
//jump over the \\
								}
								int token = isJavadoc ?  : ;
								this.[this.] = firstTag;
								if (!isJavadoc && this. <= this. && this. < this.-1){
								}
								if (this. != nullcheckTaskTag(this.this.);
								if (this.) {
									/*
									if (isJavadoc)
										return TokenNameCOMMENT_JAVADOC;
									return TokenNameCOMMENT_BLOCK;
									*/
									return token;
								}
catch (IndexOutOfBoundsException e) {
							}
							break;
						}
						if (getNextChar('='))
					}
				case '\u001a' :
					if (atEnd())
						return ;
					//the atEnd may not be <this.currentPosition == this.source.length> if source is only some part of a real (external) stream
					throw new InvalidInputException("Ctrl-Z"); //$NON-NLS-1$
				default :
					char c = this.;
								return scanNumber(false);
else {
						}
					}
					boolean isJavaIdStart;
						}
						// Unicode 4 detection
						char low = (chargetNextChar();
							// illegal low surrogate
						}
						isJavaIdStart = ScannerHelper.isJavaIdentifierStart(this.clow);
					}
					else if (c >=  && c <= ) {
						}
else {
						// optimized case already checked
						isJavaIdStart = Character.isJavaIdentifierStart(c);
					}
					if (isJavaIdStart)
					if (ScannerHelper.isDigit(this.)) {
						return scanNumber(false);
					}
			}
		}
//-----------------end switch while try--------------------
		if (this. && (whiteStart != this. - 1)) {
			// reposition scanner in case we are interested by spaces as tokens
			this. = whiteStart;
		}
	}
	/* might be completing at very end of file (e.g. behind a dot) */
	if (this. == null &&
		this. == this. + 1){
		this. = this.// for being detected as empty free identifier
	}
	return ;
public final void getNextUnicodeChar() throws InvalidInputException {
	int temp = this.// the \ is already read
	if(this. > temp) {
		this. += (this. - temp);
	}
	if (temp < this. && this. < this.-1){
	}
protected boolean isFirstTag() {
	return
		getNextChar('d') &&
		getNextChar('e') &&
		getNextChar('p') &&
		getNextChar('r') &&
		getNextChar('e') &&
		getNextChar('c') &&
		getNextChar('a') &&
		getNextChar('t') &&
		getNextChar('e') &&
public final void jumpOverBlock() {
///*
// * In case we actually read a keyword, but the cursor is located inside,
// * we pretend we read an identifier.
// */
public int scanIdentifierOrKeyword() {
	int id = super.scanIdentifierOrKeyword();
	if (this. <= this.+1
			&& this. < this.){
		// extends the end of the completion token even if the end is after eofPosition
		if (this.+1 == this.) {
			int temp = this.;
			this. = this..length;
		 	while(getNextCharAsJavaIdentifierPart()){/*empty*/}
			this. = temp;
		}
		// convert completed keyword into an identifier
	}
	return id;
public int scanNumber(boolean dotPrefixthrows InvalidInputException {
	int token = super.scanNumber(dotPrefix);
	// consider completion just before a number to be ok, will insert before it
	if (this. <= this. && this. < this.){
	}
	return token;