You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

NameConvertor.java 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. /********************************************************************
  2. * Copyright (c) 2006 Contributors. All rights reserved.
  3. * This program and the accompanying materials are made available
  4. * under the terms of the Eclipse Public License v1.0
  5. * which accompanies this distribution and is available at
  6. * http://eclipse.org/legal/epl-v10.html
  7. *
  8. * Contributors: IBM Corporation - initial API and implementation
  9. * Helen Hawkins - initial version
  10. *******************************************************************/
  11. package org.aspectj.asm.internal;
  12. public class NameConvertor {
  13. private static final char BOOLEAN = 'Z';
  14. private static final char BYTE = 'B';
  15. private static final char CHAR = 'C';
  16. private static final char DOUBLE = 'D';
  17. private static final char FLOAT = 'F';
  18. private static final char INT = 'I';
  19. private static final char LONG = 'J';
  20. private static final char SHORT = 'S';
  21. private static final char ARRAY = '[';
  22. private static final char RESOLVED = 'L';
  23. private static final char UNRESOLVED = 'Q';
  24. public static final char PARAMETERIZED = 'P';
  25. private static final char[] BOOLEAN_NAME = new char[] { 'b', 'o', 'o', 'l', 'e', 'a', 'n' };
  26. private static final char[] BYTE_NAME = new char[] { 'b', 'y', 't', 'e' };
  27. private static final char[] CHAR_NAME = new char[] { 'c', 'h', 'a', 'r' };
  28. private static final char[] DOUBLE_NAME = new char[] { 'd', 'o', 'u', 'b', 'l', 'e' };
  29. private static final char[] FLOAT_NAME = new char[] { 'f', 'l', 'o', 'a', 't' };
  30. private static final char[] INT_NAME = new char[] { 'i', 'n', 't' };
  31. private static final char[] LONG_NAME = new char[] { 'l', 'o', 'n', 'g' };
  32. private static final char[] SHORT_NAME = new char[] { 's', 'h', 'o', 'r', 't' };
  33. private static final char[] SQUARE_BRACKETS = new char[] { '[', ']' };
  34. private static final char[] GREATER_THAN = new char[] { '>' };
  35. private static final char[] LESS_THAN = new char[] { '<' };
  36. private static final char[] COMMA = new char[] { ',' };
  37. private static final char[] BACKSLASH_LESSTHAN = new char[] { '\\', '<' };
  38. private static final char[] SEMICOLON = new char[] { ';' };
  39. /**
  40. * Creates a readable name from the given char array, for example, given 'I' returns 'int'. Moreover, given
  41. * 'Ljava/lang/String;&lt;Ljava/lang/String;&gt;' returns 'java.lang.String&lt;java.lang.String&gt;'
  42. */
  43. public static char[] convertFromSignature(char[] c) {
  44. int lt = CharOperation.indexOf('<', c);
  45. int sc = CharOperation.indexOf(';', c);
  46. int gt = CharOperation.indexOf('>', c);
  47. int smallest = 0;
  48. if (lt == -1 && sc == -1 && gt == -1) {
  49. // we have something like 'Ljava/lang/String' or 'I'
  50. return getFullyQualifiedTypeName(c);
  51. } else if (lt != -1 && (sc == -1 || lt <= sc) && (gt == -1 || lt <= gt)) {
  52. // we have something like 'Ljava/lang/String<I'
  53. smallest = lt;
  54. } else if (sc != -1 && (lt == -1 || sc <= lt) && (gt == -1 || sc <= gt)) {
  55. // we have something like 'Ljava/lang/String;I'
  56. smallest = sc;
  57. } else {
  58. // we have something like '>;'
  59. smallest = gt;
  60. }
  61. char[] first = CharOperation.subarray(c, 0, smallest);
  62. char[] second = CharOperation.subarray(c, smallest + 1, c.length);
  63. if (smallest == 0 && first.length == 0 && c[0] == '>') {
  64. // c = {'>',';'} therefore we just want to return '>' to
  65. // close the generic signature
  66. return GREATER_THAN;
  67. } else if (first.length == 1 && second.length == 0) {
  68. return first;
  69. } else if (second.length == 0 || (second.length == 1 && second[0] == ';')) {
  70. // we've reached the end of the array, therefore only care about
  71. // the first part
  72. return convertFromSignature(first);
  73. } else if (smallest == lt) {
  74. // if c = 'Ljava/lang/String;<I' then first = 'Ljava/Lang/String;' and
  75. // second = 'I'. Want to end up with 'Ljava.lang.String<I' and so add
  76. // the '<' back.
  77. char[] inclLT = CharOperation.concat(convertFromSignature(first), LESS_THAN);
  78. return CharOperation.concat(inclLT, convertFromSignature(second));
  79. } else if (smallest == gt) {
  80. char[] inclLT = CharOperation.concat(convertFromSignature(first), GREATER_THAN);
  81. return CharOperation.concat(inclLT, convertFromSignature(second));
  82. } else if (second.length != 2) {
  83. // if c = 'Ljava/lang/Sting;LMyClass' then first = 'Ljava/lang/String'
  84. // and second = 'LMyClass'. Want to end up with 'java.lang.String,MyClass
  85. // so want to add a ','. However, only want to do this if we're in the
  86. // middle of a '<...>'
  87. char[] inclComma = CharOperation.concat(convertFromSignature(first), COMMA);
  88. return CharOperation.concat(inclComma, convertFromSignature(second));
  89. }
  90. return CharOperation.concat(convertFromSignature(first), convertFromSignature(second));
  91. }
  92. /**
  93. * Given a char array, returns the type name for this. For example 'I' returns 'int', 'Ljava/lang/String' returns
  94. * 'java.lang.String' and '[Ljava/lang/String' returns 'java.lang.String[]'
  95. *
  96. * NOTE: Doesn't go any deaper so given 'Ljava/lang/String;<Ljava/lang/String;>' it would return
  97. * 'java.lang.String;<Ljava.lang.String;>', however, only called with something like 'Ljava/lang/String'
  98. */
  99. private static char[] getFullyQualifiedTypeName(char[] c) {
  100. if (c.length == 0) {
  101. return c;
  102. }
  103. if (c[0] == BOOLEAN) {
  104. return BOOLEAN_NAME;
  105. } else if (c[0] == BYTE) {
  106. return BYTE_NAME;
  107. } else if (c[0] == CHAR) {
  108. return CHAR_NAME;
  109. } else if (c[0] == DOUBLE) {
  110. return DOUBLE_NAME;
  111. } else if (c[0] == FLOAT) {
  112. return FLOAT_NAME;
  113. } else if (c[0] == INT) {
  114. return INT_NAME;
  115. } else if (c[0] == LONG) {
  116. return LONG_NAME;
  117. } else if (c[0] == SHORT) {
  118. return SHORT_NAME;
  119. } else if (c[0] == ARRAY) {
  120. return CharOperation.concat(getFullyQualifiedTypeName(CharOperation.subarray(c, 1, c.length)), SQUARE_BRACKETS);
  121. } else {
  122. char[] type = CharOperation.subarray(c, 1, c.length);
  123. CharOperation.replace(type, '/', '.');
  124. return type;
  125. }
  126. }
  127. // public static char[] createShortName(char[] c) {
  128. // return createShortName(c, false);
  129. // }
  130. /**
  131. * Given 'Ppkg/MyGenericClass&lt;Ljava/lang/String;Ljava/lang/Integer;&gt;;' will return 'QMyGenericClass&lt;QString;QInteger;&gt;;'
  132. */
  133. public static char[] createShortName(char[] c, boolean haveFullyQualifiedAtLeastOneThing, boolean needsFullyQualifiedFirstEntry) {
  134. if (c[0] == '[') {
  135. char[] ret = CharOperation.concat(
  136. new char[] { '\\', '[' },
  137. createShortName(CharOperation.subarray(c, 1, c.length), haveFullyQualifiedAtLeastOneThing,
  138. needsFullyQualifiedFirstEntry));
  139. return ret;
  140. } else if (c[0] == '+') {
  141. char[] ret = CharOperation.concat(
  142. new char[] { '+' },
  143. createShortName(CharOperation.subarray(c, 1, c.length), haveFullyQualifiedAtLeastOneThing,
  144. needsFullyQualifiedFirstEntry));
  145. return ret;
  146. } else if (c[0] == '*') {
  147. return c; // c is *>;
  148. }
  149. int lt = CharOperation.indexOf('<', c);
  150. int sc = CharOperation.indexOf(';', c);
  151. int gt = CharOperation.indexOf('>', c);
  152. int smallest = 0;
  153. if (lt == -1 && sc == -1 && gt == -1) {
  154. // we have something like 'Ljava/lang/String' or 'I'
  155. if (!needsFullyQualifiedFirstEntry) {
  156. return getTypeName(c, true);
  157. } else {
  158. return getTypeName(c, haveFullyQualifiedAtLeastOneThing);
  159. }
  160. } else if (lt != -1 && (sc == -1 || lt <= sc) && (gt == -1 || lt <= gt)) {
  161. // we have something like 'Ljava/lang/String<I'
  162. smallest = lt;
  163. } else if (sc != -1 && (lt == -1 || sc <= lt) && (gt == -1 || sc <= gt)) {
  164. // we have something like 'Ljava/lang/String;I'
  165. smallest = sc;
  166. } else {
  167. // we have something like '>;'
  168. smallest = gt;
  169. }
  170. char[] first = CharOperation.subarray(c, 0, smallest);
  171. char[] second = CharOperation.subarray(c, smallest + 1, c.length);
  172. if (smallest == 0 && first.length == 0 && c[0] == '>') {
  173. // c = {'>',';'} therefore we just want to return c to
  174. // close the generic signature
  175. return c;
  176. } else if (first.length == 1 && second.length == 0) {
  177. return first;
  178. } else if (second.length == 0 || (second.length == 1 && second[0] == ';')) {
  179. // we've reached the end of the array, therefore only care about
  180. // the first part
  181. return CharOperation.concat(createShortName(first, haveFullyQualifiedAtLeastOneThing, needsFullyQualifiedFirstEntry),
  182. new char[] { ';' });
  183. } else if (smallest == lt) {
  184. // if c = 'Ljava/lang/String;<I' then first = 'Ljava/Lang/String;' and
  185. // second = 'I'. Want to end up with 'LString<I' and so add
  186. // the '<' back.
  187. char[] inclLT = CharOperation.concat(createShortName(first, haveFullyQualifiedAtLeastOneThing, true),
  188. BACKSLASH_LESSTHAN);
  189. return CharOperation.concat(inclLT, createShortName(second, true, false));
  190. } else if (smallest == gt) {
  191. char[] inclLT = CharOperation.concat(
  192. createShortName(first, haveFullyQualifiedAtLeastOneThing, needsFullyQualifiedFirstEntry), GREATER_THAN);
  193. return CharOperation.concat(inclLT, createShortName(second, true, false));
  194. } else {
  195. // if c = 'Ljava/lang/Sting;LMyClass;' then first = 'Ljava/lang/String'
  196. // and second = 'LMyClass;'. Want to end up with 'QString;QMyClass;
  197. // so add the ';' back
  198. char[] firstTypeParam = CharOperation.concat(createShortName(first, haveFullyQualifiedAtLeastOneThing, false),
  199. SEMICOLON);
  200. return CharOperation.concat(firstTypeParam, createShortName(second, true, false));
  201. }
  202. }
  203. // public static char[] getTypeName(char[] name) {
  204. // return getTypeName(name, false);
  205. // }
  206. /**
  207. * Convert a typename into its handle form. There are various cases to consider here - many are discussed in pr249216. The flag
  208. * allreadyFQd indicates if we've already included a fq'd name in what we are creating - if we have then further references
  209. * should not be fq'd and can be the short name (so java.util.Set becomes just Set).
  210. *
  211. */
  212. /**
  213. * Given 'Qjava/lang/String;' returns 'QString;'
  214. */
  215. public static char[] getTypeName(char[] name, boolean haveFullyQualifiedAtLeastOneThing) {
  216. if (!haveFullyQualifiedAtLeastOneThing) {
  217. if (name[0] == RESOLVED || name[0] == PARAMETERIZED) {
  218. char[] sub = CharOperation.subarray(name, 1, name.length);
  219. CharOperation.replace(sub, '/', '.');
  220. return CharOperation.concat(new char[] { UNRESOLVED }, sub);
  221. } else {
  222. char[] sub = CharOperation.subarray(name, 1, name.length);
  223. CharOperation.replace(sub, '/', '.');
  224. return CharOperation.concat(new char[] { name[0] }, sub);
  225. }
  226. } else {
  227. int i = CharOperation.lastIndexOf('/', name);
  228. if (i != -1) {
  229. if (name[0] == RESOLVED || name[0] == PARAMETERIZED) {
  230. return CharOperation.concat(new char[] { UNRESOLVED }, CharOperation.subarray(name, i + 1, name.length));
  231. } else {
  232. return CharOperation.concat(new char[] { name[0] }, CharOperation.subarray(name, i + 1, name.length));
  233. }
  234. }
  235. }
  236. return name;
  237. }
  238. }