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.

JDTLikeHandleProvider.java 8.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  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. import java.io.File;
  13. import java.util.Iterator;
  14. import java.util.List;
  15. import org.aspectj.asm.AsmManager;
  16. import org.aspectj.asm.IElementHandleProvider;
  17. import org.aspectj.asm.IProgramElement;
  18. import org.aspectj.bridge.ISourceLocation;
  19. import org.aspectj.util.CharOperation;
  20. import org.aspectj.util.NameConvertor;
  21. /**
  22. * Creates JDT-like handles, for example
  23. *
  24. * method with string argument: <tjp{Demo.java[Demo~main~\[QString;
  25. * method with generic argument: <pkg{MyClass.java[MyClass~myMethod~QList\<QString;>;
  26. * an aspect: <pkg*A1.aj}A1
  27. * advice with Integer arg: <pkg*A8.aj}A8&afterReturning&QInteger;
  28. * method call: <pkg*A10.aj[C~m1?method-call(void pkg.C.m2())
  29. *
  30. */
  31. public class JDTLikeHandleProvider implements IElementHandleProvider {
  32. // Need to keep our own count of the number of initializers
  33. // because this information cannot be gained from the ipe.
  34. private int initializerCounter = 0;
  35. private char[] empty = new char[]{};
  36. private char[] countDelim = new char[]{HandleProviderDelimiter.COUNT.getDelimiter()};
  37. private String backslash = "\\";
  38. private String emptyString = "";
  39. public String createHandleIdentifier(IProgramElement ipe) {
  40. // AjBuildManager.setupModel --> top of the tree is either
  41. // <root> or the .lst file
  42. if (ipe == null ||
  43. (ipe.getKind().equals(IProgramElement.Kind.FILE_JAVA)
  44. && ipe.getName().equals("<root>"))) {
  45. return "";
  46. } else if (ipe.getHandleIdentifier(false) != null) {
  47. // have already created the handle for this ipe
  48. // therefore just return it
  49. return ipe.getHandleIdentifier();
  50. } else if (ipe.getKind().equals(IProgramElement.Kind.FILE_LST)) {
  51. String configFile = AsmManager.getDefault().getHierarchy().getConfigFile();
  52. int start = configFile.lastIndexOf(File.separator);
  53. int end = configFile.lastIndexOf(".lst");
  54. if (end != -1) {
  55. configFile = configFile.substring(start+1,end);
  56. } else {
  57. configFile = configFile.substring(start+1);
  58. }
  59. ipe.setHandleIdentifier(configFile);
  60. return configFile;
  61. }
  62. IProgramElement parent = ipe.getParent();
  63. if (parent != null &&
  64. parent.getKind().equals(IProgramElement.Kind.IMPORT_REFERENCE)) {
  65. // want to miss out '#import declaration' in the handle
  66. parent = ipe.getParent().getParent();
  67. }
  68. StringBuffer handle = new StringBuffer();
  69. // add the handle for the parent
  70. handle.append(createHandleIdentifier(parent));
  71. // add the correct delimiter for this ipe
  72. handle.append(HandleProviderDelimiter.getDelimiter(ipe));
  73. // add the name and any parameters unless we're an initializer
  74. // (initializer's names are '...')
  75. if (!ipe.getKind().equals(IProgramElement.Kind.INITIALIZER)) {
  76. handle.append(ipe.getName() + getParameters(ipe));
  77. }
  78. // add the count, for example '!2' if its the second ipe of its
  79. // kind in the aspect
  80. handle.append(getCount(ipe));
  81. ipe.setHandleIdentifier(handle.toString());
  82. return handle.toString();
  83. }
  84. private String getParameters(IProgramElement ipe) {
  85. if (ipe.getParameterSignatures() == null || ipe.getParameterSignatures().isEmpty()) return "";
  86. StringBuffer sb = new StringBuffer();
  87. List parameterTypes = ipe.getParameterSignatures();
  88. for (Iterator iter = parameterTypes.iterator(); iter.hasNext();) {
  89. char[] element = (char[]) iter.next();
  90. sb.append(HandleProviderDelimiter.getDelimiter(ipe));
  91. if (element[0] == HandleProviderDelimiter.TYPE.getDelimiter()) {
  92. // its an array
  93. sb.append(HandleProviderDelimiter.ESCAPE.getDelimiter());
  94. sb.append(HandleProviderDelimiter.TYPE.getDelimiter());
  95. sb.append(NameConvertor.getTypeName(
  96. CharOperation.subarray(element,1,element.length)));
  97. } else if (element[0] == NameConvertor.PARAMETERIZED) {
  98. // its a parameterized type
  99. sb.append(NameConvertor.createShortName(element));
  100. } else {
  101. sb.append(NameConvertor.getTypeName(element));
  102. }
  103. }
  104. return sb.toString();
  105. }
  106. private char[] getCount(IProgramElement ipe) {
  107. char[] byteCodeName = ipe.getBytecodeName().toCharArray();
  108. if (ipe.getKind().isDeclare()) {
  109. int index = CharOperation.lastIndexOf('_',byteCodeName);
  110. if (index != -1) {
  111. return convertCount(CharOperation.subarray(byteCodeName,
  112. index+1,byteCodeName.length));
  113. }
  114. } else if (ipe.getKind().equals(IProgramElement.Kind.ADVICE)) {
  115. int lastDollar = CharOperation.lastIndexOf('$',byteCodeName);
  116. if (lastDollar != -1) {
  117. char[] upToDollar = CharOperation.subarray(byteCodeName,0,lastDollar);
  118. int secondToLastDollar = CharOperation.lastIndexOf('$',upToDollar);
  119. if (secondToLastDollar != -1) {
  120. return convertCount(CharOperation.subarray(upToDollar,
  121. secondToLastDollar+1,upToDollar.length));
  122. }
  123. }
  124. } else if (ipe.getKind().equals(IProgramElement.Kind.INITIALIZER)) {
  125. return String.valueOf(++initializerCounter).toCharArray();
  126. } else if (ipe.getKind().equals(IProgramElement.Kind.CODE)) {
  127. int index = CharOperation.lastIndexOf('!',byteCodeName);
  128. if (index != -1) {
  129. return convertCount(CharOperation.subarray(byteCodeName,
  130. index+1,byteCodeName.length));
  131. }
  132. }
  133. return empty;
  134. }
  135. /**
  136. * Only returns the count if it's not equal to 1
  137. */
  138. private char[] convertCount(char[] c) {
  139. if ((c.length == 1 && c[0] != ' ' && c[0] != '1') || c.length > 1) {
  140. return CharOperation.concat(countDelim,c);
  141. }
  142. return empty;
  143. }
  144. public String getFileForHandle(String handle) {
  145. IProgramElement node = AsmManager.getDefault().getHierarchy().getElement(handle);
  146. if (node != null) {
  147. return AsmManager.getDefault().getCanonicalFilePath(node.getSourceLocation().getSourceFile());
  148. } else if (handle.charAt(0) == HandleProviderDelimiter.ASPECT_CU.getDelimiter()
  149. || handle.charAt(0) == HandleProviderDelimiter.COMPILATIONUNIT.getDelimiter()) {
  150. // it's something like *MyAspect.aj or {MyClass.java. In other words
  151. // it's a file node that's been created with no children and no parent
  152. return backslash + handle.substring(1);
  153. }
  154. return emptyString;
  155. }
  156. public int getLineNumberForHandle(String handle) {
  157. IProgramElement node = AsmManager.getDefault().getHierarchy().getElement(handle);
  158. if (node != null) {
  159. return node.getSourceLocation().getLine();
  160. } else if (handle.charAt(0) == HandleProviderDelimiter.ASPECT_CU.getDelimiter()
  161. || handle.charAt(0) == HandleProviderDelimiter.COMPILATIONUNIT.getDelimiter()) {
  162. // it's something like *MyAspect.aj or {MyClass.java. In other words
  163. // it's a file node that's been created with no children and no parent
  164. return 1;
  165. }
  166. return -1;
  167. }
  168. public int getOffSetForHandle(String handle) {
  169. IProgramElement node = AsmManager.getDefault().getHierarchy().getElement(handle);
  170. if (node != null) {
  171. return node.getSourceLocation().getOffset();
  172. } else if (handle.charAt(0) == HandleProviderDelimiter.ASPECT_CU.getDelimiter()
  173. || handle.charAt(0) == HandleProviderDelimiter.COMPILATIONUNIT.getDelimiter()) {
  174. // it's something like *MyAspect.aj or {MyClass.java. In other words
  175. // it's a file node that's been created with no children and no parent
  176. return 0;
  177. }
  178. return -1;
  179. }
  180. public String createHandleIdentifier(ISourceLocation location) {
  181. IProgramElement node = AsmManager.getDefault().getHierarchy().findElementForSourceLine(location);
  182. if (node != null) {
  183. return createHandleIdentifier(node);
  184. }
  185. return null;
  186. }
  187. public String createHandleIdentifier(File sourceFile, int line, int column, int offset) {
  188. IProgramElement node = AsmManager.getDefault().getHierarchy().findElementForOffSet(sourceFile.getAbsolutePath(),line,offset);
  189. if (node != null) {
  190. return createHandleIdentifier(node);
  191. }
  192. return null;
  193. }
  194. public boolean dependsOnLocation() {
  195. // handles are independent of soureLocations therefore return false
  196. return false;
  197. }
  198. public void initialize() {
  199. // reset the initializer count. This ensures we return the
  200. // same handle as JDT for initializers.
  201. initializerCounter = 0;
  202. }
  203. }