|
|
@@ -0,0 +1,214 @@ |
|
|
|
/******************************************************************** |
|
|
|
* Copyright (c) 2006 Contributors. 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://eclipse.org/legal/epl-v10.html |
|
|
|
* |
|
|
|
* Contributors: IBM Corporation - initial API and implementation |
|
|
|
* Helen Hawkins - initial version |
|
|
|
*******************************************************************/ |
|
|
|
package org.aspectj.asm.internal; |
|
|
|
|
|
|
|
|
|
|
|
public class NameConvertor { |
|
|
|
|
|
|
|
private static final char BOOLEAN = 'Z'; |
|
|
|
private static final char BYTE = 'B'; |
|
|
|
private static final char CHAR = 'C'; |
|
|
|
private static final char DOUBLE = 'D'; |
|
|
|
private static final char FLOAT = 'F'; |
|
|
|
private static final char INT = 'I'; |
|
|
|
private static final char LONG = 'J'; |
|
|
|
private static final char SHORT = 'S'; |
|
|
|
private static final char ARRAY = '['; |
|
|
|
private static final char RESOLVED = 'L'; |
|
|
|
private static final char UNRESOLVED = 'Q'; |
|
|
|
|
|
|
|
public static final char PARAMETERIZED = 'P'; |
|
|
|
|
|
|
|
private static final char[] BOOLEAN_NAME = new char[]{'b','o','o','l','e','a','n'}; |
|
|
|
private static final char[] BYTE_NAME = new char[]{'b','y','t','e'}; |
|
|
|
private static final char[] CHAR_NAME = new char[]{'c','h','a','r'}; |
|
|
|
private static final char[] DOUBLE_NAME = new char[]{'d','o','u','b','l','e'}; |
|
|
|
private static final char[] FLOAT_NAME = new char[]{'f','l','o','a','t'}; |
|
|
|
private static final char[] INT_NAME = new char[]{'i','n','t'}; |
|
|
|
private static final char[] LONG_NAME = new char[]{'l','o','n','g'}; |
|
|
|
private static final char[] SHORT_NAME = new char[]{'s','h','o','r','t'}; |
|
|
|
|
|
|
|
private static final char[] SQUARE_BRACKETS = new char[]{'[',']'}; |
|
|
|
private static final char[] GREATER_THAN = new char[]{'>'}; |
|
|
|
private static final char[] LESS_THAN = new char[]{'<'}; |
|
|
|
private static final char[] COMMA = new char[]{','}; |
|
|
|
private static final char[] BACKSLASH_LESSTHAN = new char[]{'\\','<'}; |
|
|
|
private static final char[] SEMICOLON = new char[]{';'}; |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* Creates a readable name from the given char array, for example, |
|
|
|
* given 'I' returns 'int'. Moreover, given |
|
|
|
* 'Ljava/lang/String;<Ljava/lang/String;>' returns |
|
|
|
* 'java.lang.String<java.lang.String>' |
|
|
|
*/ |
|
|
|
public static char[] convertFromSignature(char[] c) { |
|
|
|
int lt = CharOperation.indexOf('<',c); |
|
|
|
int sc = CharOperation.indexOf(';',c); |
|
|
|
int gt = CharOperation.indexOf('>',c); |
|
|
|
|
|
|
|
int smallest = 0; |
|
|
|
if (lt == -1 && sc == -1 && gt == -1) { |
|
|
|
// we have something like 'Ljava/lang/String' or 'I' |
|
|
|
return getFullyQualifiedTypeName(c); |
|
|
|
} else if (lt != -1 && (sc == -1 || lt <= sc) && (gt == -1 || lt <= gt)) { |
|
|
|
// we have something like 'Ljava/lang/String<I' |
|
|
|
smallest = lt; |
|
|
|
} else if (sc != -1 && (lt == -1 || sc <= lt) && (gt == -1 || sc <= gt)) { |
|
|
|
// we have something like 'Ljava/lang/String;I' |
|
|
|
smallest = sc; |
|
|
|
} else { |
|
|
|
// we have something like '>;' |
|
|
|
smallest = gt; |
|
|
|
} |
|
|
|
char[] first = CharOperation.subarray(c,0,smallest); |
|
|
|
char[] second = CharOperation.subarray(c,smallest+1,c.length); |
|
|
|
if (smallest == 0 && first.length == 0 && c[0] == '>') { |
|
|
|
// c = {'>',';'} therefore we just want to return '>' to |
|
|
|
// close the generic signature |
|
|
|
return GREATER_THAN; |
|
|
|
} else if (first.length == 1 && second.length == 0) { |
|
|
|
return first; |
|
|
|
} else if (second.length == 0 || (second.length == 1 && second[0] == ';')){ |
|
|
|
// we've reached the end of the array, therefore only care about |
|
|
|
// the first part |
|
|
|
return convertFromSignature(first); |
|
|
|
} else if (smallest == lt) { |
|
|
|
// if c = 'Ljava/lang/String;<I' then first = 'Ljava/Lang/String;' and |
|
|
|
// second = 'I'. Want to end up with 'Ljava.lang.String<I' and so add |
|
|
|
// the '<' back. |
|
|
|
char[] inclLT = CharOperation.concat(convertFromSignature(first),LESS_THAN); |
|
|
|
return CharOperation.concat(inclLT,convertFromSignature(second)); |
|
|
|
} else if (smallest == gt) { |
|
|
|
char[] inclLT = CharOperation.concat(convertFromSignature(first),GREATER_THAN); |
|
|
|
return CharOperation.concat(inclLT,convertFromSignature(second)); |
|
|
|
} else if (second.length != 2) { |
|
|
|
// if c = 'Ljava/lang/Sting;LMyClass' then first = 'Ljava/lang/String' |
|
|
|
// and second = 'LMyClass'. Want to end up with 'java.lang.String,MyClass |
|
|
|
// so want to add a ','. However, only want to do this if we're in the |
|
|
|
// middle of a '<...>' |
|
|
|
char[] inclComma = CharOperation.concat(convertFromSignature(first),COMMA); |
|
|
|
return CharOperation.concat(inclComma,convertFromSignature(second)); |
|
|
|
} |
|
|
|
return CharOperation.concat(convertFromSignature(first),convertFromSignature(second)); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* Given a char array, returns the type name for this. For example |
|
|
|
* 'I' returns 'int', 'Ljava/lang/String' returns 'java.lang.String' and |
|
|
|
* '[Ljava/lang/String' returns 'java.lang.String[]' |
|
|
|
* |
|
|
|
* NOTE: Doesn't go any deaper so given 'Ljava/lang/String;<Ljava/lang/String;>' |
|
|
|
* it would return 'java.lang.String;<Ljava.lang.String;>', however, only called |
|
|
|
* with something like 'Ljava/lang/String' |
|
|
|
*/ |
|
|
|
private static char[] getFullyQualifiedTypeName(char[] c) { |
|
|
|
if (c.length == 0) { |
|
|
|
return c; |
|
|
|
} |
|
|
|
if (c[0] == BOOLEAN) { |
|
|
|
return BOOLEAN_NAME; |
|
|
|
} else if (c[0] == BYTE) { |
|
|
|
return BYTE_NAME; |
|
|
|
} else if (c[0] == CHAR) { |
|
|
|
return CHAR_NAME; |
|
|
|
} else if (c[0] == DOUBLE) { |
|
|
|
return DOUBLE_NAME; |
|
|
|
} else if (c[0] == FLOAT) { |
|
|
|
return FLOAT_NAME; |
|
|
|
} else if (c[0] == INT) { |
|
|
|
return INT_NAME; |
|
|
|
} else if (c[0] == LONG) { |
|
|
|
return LONG_NAME; |
|
|
|
} else if (c[0] == SHORT) { |
|
|
|
return SHORT_NAME; |
|
|
|
} else if (c[0] == ARRAY) { |
|
|
|
return CharOperation.concat( |
|
|
|
getFullyQualifiedTypeName(CharOperation.subarray(c,1,c.length)), |
|
|
|
SQUARE_BRACKETS); |
|
|
|
} else { |
|
|
|
char[] type = CharOperation.subarray(c,1,c.length); |
|
|
|
CharOperation.replace(type,'/','.'); |
|
|
|
return type; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Given 'Ppkg/MyGenericClass<Ljava/lang/String;Ljava/lang/Integer;>;' |
|
|
|
* will return 'QMyGenericClass<QString;QInteger;>;' |
|
|
|
*/ |
|
|
|
public static char[] createShortName(char[] c) { |
|
|
|
int lt = CharOperation.indexOf('<',c); |
|
|
|
int sc = CharOperation.indexOf(';',c); |
|
|
|
int gt = CharOperation.indexOf('>',c); |
|
|
|
|
|
|
|
int smallest = 0; |
|
|
|
if (lt == -1 && sc == -1 && gt == -1) { |
|
|
|
// we have something like 'Ljava/lang/String' or 'I' |
|
|
|
return getTypeName(c); |
|
|
|
} else if (lt != -1 && (sc == -1 || lt <= sc) && (gt == -1 || lt <= gt)) { |
|
|
|
// we have something like 'Ljava/lang/String<I' |
|
|
|
smallest = lt; |
|
|
|
} else if (sc != -1 && (lt == -1 || sc <= lt) && (gt == -1 || sc <= gt)) { |
|
|
|
// we have something like 'Ljava/lang/String;I' |
|
|
|
smallest = sc; |
|
|
|
} else { |
|
|
|
// we have something like '>;' |
|
|
|
smallest = gt; |
|
|
|
} |
|
|
|
char[] first = CharOperation.subarray(c,0,smallest); |
|
|
|
char[] second = CharOperation.subarray(c,smallest+1,c.length); |
|
|
|
if (smallest == 0 && first.length == 0 && c[0] == '>') { |
|
|
|
// c = {'>',';'} therefore we just want to return c to |
|
|
|
// close the generic signature |
|
|
|
return c; |
|
|
|
} else if (first.length == 1 && second.length == 0) { |
|
|
|
return first; |
|
|
|
} else if (second.length == 0 || (second.length == 1 && second[0] == ';')){ |
|
|
|
// we've reached the end of the array, therefore only care about |
|
|
|
// the first part |
|
|
|
return createShortName(first); |
|
|
|
} else if (smallest == lt) { |
|
|
|
// if c = 'Ljava/lang/String;<I' then first = 'Ljava/Lang/String;' and |
|
|
|
// second = 'I'. Want to end up with 'LString<I' and so add |
|
|
|
// the '<' back. |
|
|
|
char[] inclLT = CharOperation.concat(createShortName(first),BACKSLASH_LESSTHAN); |
|
|
|
return CharOperation.concat(inclLT,createShortName(second)); |
|
|
|
} else if (smallest == gt) { |
|
|
|
char[] inclLT = CharOperation.concat(createShortName(first),GREATER_THAN); |
|
|
|
return CharOperation.concat(inclLT,createShortName(second)); |
|
|
|
} else { |
|
|
|
// if c = 'Ljava/lang/Sting;LMyClass;' then first = 'Ljava/lang/String' |
|
|
|
// and second = 'LMyClass;'. Want to end up with 'QString;QMyClass; |
|
|
|
// so add the ';' back |
|
|
|
char[] firstTypeParam = CharOperation.concat(createShortName(first),SEMICOLON); |
|
|
|
return CharOperation.concat(firstTypeParam,createShortName(second)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Given 'Qjava/lang/String;' returns 'QString;' |
|
|
|
*/ |
|
|
|
public static char[] getTypeName(char[] name) { |
|
|
|
int i = CharOperation.lastIndexOf('/',name); |
|
|
|
if (i != -1) { |
|
|
|
if (name[0] == RESOLVED || name[0] == PARAMETERIZED) { |
|
|
|
return CharOperation.concat(new char[]{UNRESOLVED}, |
|
|
|
CharOperation.subarray(name,i+1,name.length)); |
|
|
|
} else { |
|
|
|
return CharOperation.concat(new char[]{name[0]}, |
|
|
|
CharOperation.subarray(name,i+1,name.length)); |
|
|
|
} |
|
|
|
} |
|
|
|
return name; |
|
|
|
} |
|
|
|
} |