blob: 59d14938761137ab6af26d0850baad56291c0b99 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2012 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jdt.internal.debug.eval.ast.instructions;
import org.eclipse.jdt.core.compiler.CharOperation;
/**
* Copy of org.eclipse.jdt.core.Signature. The class is copied here solely for
* the purpose of commenting out the line: CharOperation.replace(result,
* C_DOLLAR, C_DOT); in the method toCharArray(char[]). See Bug 22165
*/
public class RuntimeSignature {
public static final char C_BOOLEAN = 'Z';
public static final char C_BYTE = 'B';
public static final char C_CHAR = 'C';
public static final char C_DOUBLE = 'D';
public static final char C_FLOAT = 'F';
public static final char C_INT = 'I';
public static final char C_SEMICOLON = ';';
public static final char C_LONG = 'J';
public static final char C_SHORT = 'S';
public static final char C_VOID = 'V';
public static final char C_DOT = '.';
public static final char C_DOLLAR = '$';
public static final char C_ARRAY = '[';
public static final char C_RESOLVED = 'L';
public static final char C_UNRESOLVED = 'Q';
public static final char C_NAME_END = ';';
public static final char C_PARAM_START = '(';
public static final char C_PARAM_END = ')';
public static final String SIG_BOOLEAN = "Z"; //$NON-NLS-1$
public static final String SIG_BYTE = "B"; //$NON-NLS-1$
public static final String SIG_CHAR = "C"; //$NON-NLS-1$
public static final String SIG_DOUBLE = "D"; //$NON-NLS-1$
public static final String SIG_FLOAT = "F"; //$NON-NLS-1$
public static final String SIG_INT = "I"; //$NON-NLS-1$
public static final String SIG_LONG = "J"; //$NON-NLS-1$
public static final String SIG_SHORT = "S"; //$NON-NLS-1$
public static final String SIG_VOID = "V"; //$NON-NLS-1$
private static final char[] NO_CHAR = new char[0];
private static final char[] BOOLEAN = { 'b', 'o', 'o', 'l', 'e', 'a', 'n' };
private static final char[] BYTE = { 'b', 'y', 't', 'e' };
private static final char[] CHAR = { 'c', 'h', 'a', 'r' };
private static final char[] DOUBLE = { 'd', 'o', 'u', 'b', 'l', 'e' };
private static final char[] FLOAT = { 'f', 'l', 'o', 'a', 't' };
private static final char[] INT = { 'i', 'n', 't' };
private static final char[] LONG = { 'l', 'o', 'n', 'g' };
private static final char[] SHORT = { 's', 'h', 'o', 'r', 't' };
private static final char[] VOID = { 'v', 'o', 'i', 'd' };
public static String toString(String signature)
throws IllegalArgumentException {
return new String(toCharArray(signature.toCharArray()));
}
public static char[] toCharArray(char[] signature)
throws IllegalArgumentException {
try {
int sigLength = signature.length;
if (sigLength == 0 || signature[0] == C_PARAM_START) {
return toCharArray(signature, NO_CHAR, null, true, true);
}
// compute result length
int resultLength = 0;
int index = -1;
while (signature[++index] == C_ARRAY) {
resultLength += 2; // []
}
switch (signature[index]) {
case C_BOOLEAN:
resultLength += BOOLEAN.length;
break;
case C_BYTE:
resultLength += BYTE.length;
break;
case C_CHAR:
resultLength += CHAR.length;
break;
case C_DOUBLE:
resultLength += DOUBLE.length;
break;
case C_FLOAT:
resultLength += FLOAT.length;
break;
case C_INT:
resultLength += INT.length;
break;
case C_LONG:
resultLength += LONG.length;
break;
case C_SHORT:
resultLength += SHORT.length;
break;
case C_VOID:
resultLength += VOID.length;
break;
case C_RESOLVED:
case C_UNRESOLVED:
int end = CharOperation.indexOf(C_SEMICOLON, signature, index);
if (end == -1)
throw new IllegalArgumentException();
int start = index + 1;
resultLength += end - start;
break;
default:
throw new IllegalArgumentException();
}
char[] result = new char[resultLength];
copyType(signature, 0, result, 0, true);
/**
* Converts '$' separated type signatures into '.' separated type
* signature. NOTE: This assumes that the type signature is an inner
* type signature. This is true in most cases, but someone can
* define a non-inner type name containing a '$'. However to tell
* the difference, we would have to resolve the signature, which
* cannot be done at this point.
*/
// CharOperation.replace(result, C_DOLLAR, C_DOT);
return result;
} catch (ArrayIndexOutOfBoundsException e) {
throw new IllegalArgumentException();
}
}
public static char[] toCharArray(char[] methodSignature, char[] methodName,
char[][] parameterNames, boolean fullyQualifyTypeNames,
boolean includeReturnType) {
try {
int firstParen = CharOperation.indexOf(C_PARAM_START,
methodSignature);
if (firstParen == -1)
throw new IllegalArgumentException();
int sigLength = methodSignature.length;
// compute result length
// method signature
int paramCount = 0;
int lastParen = -1;
int resultLength = 0;
signature: for (int i = firstParen; i < sigLength; i++) {
switch (methodSignature[i]) {
case C_ARRAY:
resultLength += 2; // []
continue signature;
case C_BOOLEAN:
resultLength += BOOLEAN.length;
break;
case C_BYTE:
resultLength += BYTE.length;
break;
case C_CHAR:
resultLength += CHAR.length;
break;
case C_DOUBLE:
resultLength += DOUBLE.length;
break;
case C_FLOAT:
resultLength += FLOAT.length;
break;
case C_INT:
resultLength += INT.length;
break;
case C_LONG:
resultLength += LONG.length;
break;
case C_SHORT:
resultLength += SHORT.length;
break;
case C_VOID:
resultLength += VOID.length;
break;
case C_RESOLVED:
case C_UNRESOLVED:
int end = CharOperation.indexOf(C_SEMICOLON,
methodSignature, i);
if (end == -1)
throw new IllegalArgumentException();
int start;
if (fullyQualifyTypeNames) {
start = i + 1;
} else {
start = CharOperation.lastIndexOf(C_DOT,
methodSignature, i, end) + 1;
if (start == 0)
start = i + 1;
}
resultLength += end - start;
i = end;
break;
case C_PARAM_START:
// add space for "("
resultLength++;
continue signature;
case C_PARAM_END:
lastParen = i;
if (includeReturnType) {
if (paramCount > 0) {
// remove space for ", " that was added with last
// parameter and remove space that is going to be
// added for ", " after return type
// and add space for ") "
resultLength -= 2;
} // else
// remove space that is going to be added for ", "
// after return type
// and add space for ") "
// -> noop
// decrement param count because it is going to be added
// for return type
paramCount--;
continue signature;
}
if (paramCount > 0) {
// remove space for ", " that was added with last
// parameter and add space for ")"
resultLength--;
} else {
// add space for ")"
resultLength++;
}
break signature;
default:
throw new IllegalArgumentException();
}
resultLength += 2; // add space for ", "
paramCount++;
}
// parameter names
if(parameterNames != null) {
for (char[] parameterName : parameterNames) {
resultLength += parameterName.length + 1;
// parameter name + space
}
}
// selector
int selectorLength = methodName == null ? 0 : methodName.length;
resultLength += selectorLength;
// create resulting char array
char[] result = new char[resultLength];
// returned type
int index = 0;
if (includeReturnType) {
long pos = copyType(methodSignature, lastParen + 1, result,
index, fullyQualifyTypeNames);
index = (int) (pos >>> 32);
result[index++] = ' ';
}
// selector
if (methodName != null) {
System.arraycopy(methodName, 0, result, index, selectorLength);
index += selectorLength;
}
// parameters
result[index++] = C_PARAM_START;
int sigPos = firstParen + 1;
for (int i = 0; i < paramCount; i++) {
long pos = copyType(methodSignature, sigPos, result, index,
fullyQualifyTypeNames);
index = (int) (pos >>> 32);
sigPos = (int) pos;
if (parameterNames != null) {
result[index++] = ' ';
char[] parameterName = parameterNames[i];
int paramLength = parameterName.length;
System.arraycopy(parameterName, 0, result, index,
paramLength);
index += paramLength;
}
if (i != paramCount - 1) {
result[index++] = ',';
result[index++] = ' ';
}
}
if (sigPos >= sigLength) {
throw new IllegalArgumentException();
// should be on last paren
}
result[index++] = C_PARAM_END;
return result;
} catch (ArrayIndexOutOfBoundsException e) {
throw new IllegalArgumentException();
}
}
private static long copyType(char[] signature, int sigPos, char[] dest,
int index, boolean fullyQualifyTypeNames) {
int arrayCount = 0;
loop: while (true) {
switch (signature[sigPos++]) {
case C_ARRAY:
arrayCount++;
break;
case C_BOOLEAN:
int length = BOOLEAN.length;
System.arraycopy(BOOLEAN, 0, dest, index, length);
index += length;
break loop;
case C_BYTE:
length = BYTE.length;
System.arraycopy(BYTE, 0, dest, index, length);
index += length;
break loop;
case C_CHAR:
length = CHAR.length;
System.arraycopy(CHAR, 0, dest, index, length);
index += length;
break loop;
case C_DOUBLE:
length = DOUBLE.length;
System.arraycopy(DOUBLE, 0, dest, index, length);
index += length;
break loop;
case C_FLOAT:
length = FLOAT.length;
System.arraycopy(FLOAT, 0, dest, index, length);
index += length;
break loop;
case C_INT:
length = INT.length;
System.arraycopy(INT, 0, dest, index, length);
index += length;
break loop;
case C_LONG:
length = LONG.length;
System.arraycopy(LONG, 0, dest, index, length);
index += length;
break loop;
case C_SHORT:
length = SHORT.length;
System.arraycopy(SHORT, 0, dest, index, length);
index += length;
break loop;
case C_VOID:
length = VOID.length;
System.arraycopy(VOID, 0, dest, index, length);
index += length;
break loop;
case C_RESOLVED:
case C_UNRESOLVED:
int end = CharOperation.indexOf(C_SEMICOLON, signature, sigPos);
if (end == -1)
throw new IllegalArgumentException();
int start;
if (fullyQualifyTypeNames) {
start = sigPos;
} else {
start = CharOperation.lastIndexOf(C_DOT, signature, sigPos,
end) + 1;
if (start == 0)
start = sigPos;
}
length = end - start;
System.arraycopy(signature, start, dest, index, length);
sigPos = end + 1;
index += length;
break loop;
}
}
while (arrayCount-- > 0) {
dest[index++] = '[';
dest[index++] = ']';
}
return (((long) index) << 32) + sigPos;
}
}