blob: 9f45b2a06bf3feed0a50430274a949b051ca809d [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jdt.core.dom;
import org.eclipse.jdt.core.compiler.CharOperation;
/**
* Internal class.
* @since 3.1
*/
class BindingKeyScanner {
static final int START = -1;
static final int PACKAGE = 0;
static final int TYPE = 1;
static final int FIELD = 2;
static final int METHOD = 3;
static final int ARRAY = 4;
static final int TYPE_PARAMETER = 5;
static final int LOCAL_VAR = 6;
static final int END = 7;
int index = 0, start;
char[] source;
int token = START;
BindingKeyScanner(char[] source) {
this.source = source;
}
char[] getTokenSource() {
int length = this.index-this.start;
char[] result = new char[length];
System.arraycopy(this.source, this.start, result, 0, length);
return result;
}
boolean isAtFieldOrMethodStart() {
return
this.index+1 < this.source.length
&& this.source[this.index+1] == '.';
}
boolean isAtLocalVariableStart() {
return
this.index < this.source.length
&& this.source[this.index] == '#';
}
boolean isAtMemberTypeStart() {
return
this.index < this.source.length
&& (this.source[this.index] == '$'
|| (this.source[this.index] == '.' && this.source[this.index-1] == '>'));
}
boolean isAtParametersStart() {
char currentChar;
return
this.index > 0
&& this.index < this.source.length
&& ((currentChar = this.source[this.index]) == '<'
|| currentChar == '%');
}
boolean isAtTypeParameterStart() {
return
this.index+1 < this.source.length
&& this.source[this.index+1] == 'T';
}
boolean isAtTypeStart() {
return this.index+1 < this.source.length && "LIZVCDBFJS[".indexOf(this.source[this.index+1]) != -1; //$NON-NLS-1$
}
boolean isAtWildCardStart() {
return this.index+1 < this.source.length && "*+-".indexOf(this.source[this.index+1]) != -1; //$NON-NLS-1$
}
int nextToken() {
int previousTokenEnd = this.index;
this.start = this.index;
int length = this.source.length;
while (this.index <= length) {
char currentChar = this.index == length ? Character.MIN_VALUE : this.source[this.index];
switch (currentChar) {
case 'B':
case 'C':
case 'D':
case 'F':
case 'I':
case 'J':
case 'S':
case 'V':
case 'Z':
// base type
if (this.index == previousTokenEnd) {
this.index++;
this.token = TYPE;
return this.token;
}
break;
case 'L':
case 'T':
if (this.index == previousTokenEnd) {
this.start = this.index+1;
}
break;
case ';':
case '$':
if (this.index == previousTokenEnd) {
this.start = this.index+1;
previousTokenEnd = this.start;
} else {
this.token = TYPE;
return this.token;
}
break;
case '.':
case '%':
this.start = this.index+1;
previousTokenEnd = this.start;
break;
case '[':
while (this.index < length && this.source[this.index] == '[')
this.index++;
this.token = ARRAY;
return this.token;
case '<':
if (this.index == previousTokenEnd) {
this.start = this.index+1;
previousTokenEnd = this.start;
} else if (this.start > 0) {
switch (this.source[this.start-1]) {
case '.':
if (this.source[this.start-2] == '>')
// case of member type where enclosing type is parameterized
this.token = TYPE;
else
this.token = METHOD;
return this.token;
default:
this.token = TYPE;
return this.token;
}
}
break;
case '(':
this.token = METHOD;
return this.token;
case ')':
this.start = ++this.index;
this.token = END;
return this.token;
case ':':
this.token = TYPE_PARAMETER;
return this.token;
case '#':
if (this.index == previousTokenEnd) {
this.start = this.index+1;
previousTokenEnd = this.start;
} else {
this.token = LOCAL_VAR;
return this.token;
}
break;
case Character.MIN_VALUE:
switch (this.token) {
case START:
this.token = PACKAGE;
break;
case METHOD:
case LOCAL_VAR:
this.token = LOCAL_VAR;
break;
case TYPE:
if (this.index > this.start && this.source[this.start-1] == '.')
this.token = FIELD;
else
this.token = END;
break;
default:
this.token = END;
break;
}
return this.token;
case '*':
case '+':
case '-':
this.index++;
this.token = TYPE;
return this.token;
}
this.index++;
}
this.token = END;
return this.token;
}
void skipMethodSignature() {
char currentChar;
while (this.index < this.source.length && (currentChar = this.source[this.index]) != '#' && currentChar != '%')
this.index++;
}
void skipParametersEnd() {
while (this.index < this.source.length && this.source[this.index] != '>')
this.index++;
this.index++;
}
public String toString() {
StringBuffer buffer = new StringBuffer();
switch (this.token) {
case START:
buffer.append("START: "); //$NON-NLS-1$
break;
case PACKAGE:
buffer.append("PACKAGE: "); //$NON-NLS-1$
break;
case TYPE:
buffer.append("TYPE: "); //$NON-NLS-1$
break;
case FIELD:
buffer.append("FIELD: "); //$NON-NLS-1$
break;
case METHOD:
buffer.append("METHOD: "); //$NON-NLS-1$
break;
case ARRAY:
buffer.append("ARRAY: "); //$NON-NLS-1$
break;
case TYPE_PARAMETER:
buffer.append("TYPE PARAMETER: "); //$NON-NLS-1$
break;
case LOCAL_VAR:
buffer.append("LOCAL VAR: "); //$NON-NLS-1$
break;
case END:
buffer.append("END: "); //$NON-NLS-1$
break;
}
if (this.index < 0) {
buffer.append("**"); //$NON-NLS-1$
buffer.append(this.source);
} else if (this.index <= this.source.length) {
buffer.append(CharOperation.subarray(this.source, 0, this.start));
buffer.append('*');
if (this.start <= this.index) {
buffer.append(CharOperation.subarray(this.source, this.start, this.index));
buffer.append('*');
buffer.append(CharOperation.subarray(this.source, this.index, this.source.length));
} else {
buffer.append('*');
buffer.append(CharOperation.subarray(this.source, this.start, this.source.length));
}
} else {
buffer.append(this.source);
buffer.append("**"); //$NON-NLS-1$
}
return buffer.toString();
}
}