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.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  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. String fileName = configFile.substring(start + 1,end);
  55. ipe.setHandleIdentifier(fileName);
  56. return fileName;
  57. }
  58. IProgramElement parent = ipe.getParent();
  59. if (parent != null &&
  60. parent.getKind().equals(IProgramElement.Kind.IMPORT_REFERENCE)) {
  61. // want to miss out '#import declaration' in the handle
  62. parent = ipe.getParent().getParent();
  63. }
  64. StringBuffer handle = new StringBuffer();
  65. // add the handle for the parent
  66. handle.append(createHandleIdentifier(parent));
  67. // add the correct delimiter for this ipe
  68. handle.append(HandleProviderDelimiter.getDelimiter(ipe));
  69. // add the name and any parameters unless we're an initializer
  70. // (initializer's names are '...')
  71. if (!ipe.getKind().equals(IProgramElement.Kind.INITIALIZER)) {
  72. handle.append(ipe.getName() + getParameters(ipe));
  73. }
  74. // add the count, for example '!2' if its the second ipe of its
  75. // kind in the aspect
  76. handle.append(getCount(ipe));
  77. ipe.setHandleIdentifier(handle.toString());
  78. return handle.toString();
  79. }
  80. private String getParameters(IProgramElement ipe) {
  81. if (ipe.getParameterSignatures() == null || ipe.getParameterSignatures().isEmpty()) return "";
  82. StringBuffer sb = new StringBuffer();
  83. List parameterTypes = ipe.getParameterSignatures();
  84. for (Iterator iter = parameterTypes.iterator(); iter.hasNext();) {
  85. char[] element = (char[]) iter.next();
  86. sb.append(HandleProviderDelimiter.getDelimiter(ipe));
  87. if (element[0] == HandleProviderDelimiter.TYPE.getDelimiter()) {
  88. // its an array
  89. sb.append(HandleProviderDelimiter.ESCAPE.getDelimiter());
  90. sb.append(HandleProviderDelimiter.TYPE.getDelimiter());
  91. sb.append(NameConvertor.getTypeName(
  92. CharOperation.subarray(element,1,element.length)));
  93. } else if (element[0] == NameConvertor.PARAMETERIZED) {
  94. // its a parameterized type
  95. sb.append(NameConvertor.createShortName(element));
  96. } else {
  97. sb.append(NameConvertor.getTypeName(element));
  98. }
  99. }
  100. return sb.toString();
  101. }
  102. private char[] getCount(IProgramElement ipe) {
  103. char[] byteCodeName = ipe.getBytecodeName().toCharArray();
  104. if (ipe.getKind().isDeclare()) {
  105. int index = CharOperation.lastIndexOf('_',byteCodeName);
  106. if (index != -1) {
  107. return convertCount(CharOperation.subarray(byteCodeName,
  108. index+1,byteCodeName.length));
  109. }
  110. } else if (ipe.getKind().equals(IProgramElement.Kind.ADVICE)) {
  111. int lastDollar = CharOperation.lastIndexOf('$',byteCodeName);
  112. if (lastDollar != -1) {
  113. char[] upToDollar = CharOperation.subarray(byteCodeName,0,lastDollar);
  114. int secondToLastDollar = CharOperation.lastIndexOf('$',upToDollar);
  115. if (secondToLastDollar != -1) {
  116. return convertCount(CharOperation.subarray(upToDollar,
  117. secondToLastDollar+1,upToDollar.length));
  118. }
  119. }
  120. } else if (ipe.getKind().equals(IProgramElement.Kind.INITIALIZER)) {
  121. return String.valueOf(++initializerCounter).toCharArray();
  122. }
  123. return empty;
  124. }
  125. /**
  126. * Only returns the count if it's not equal to 1
  127. */
  128. private char[] convertCount(char[] c) {
  129. if ((c.length == 1 && c[0] != ' ' && c[0] != '1') || c.length > 1) {
  130. return CharOperation.concat(countDelim,c);
  131. }
  132. return empty;
  133. }
  134. public String getFileForHandle(String handle) {
  135. IProgramElement node = AsmManager.getDefault().getHierarchy().getElement(handle);
  136. if (node != null) {
  137. return AsmManager.getDefault().getCanonicalFilePath(node.getSourceLocation().getSourceFile());
  138. } else if (handle.charAt(0) == HandleProviderDelimiter.ASPECT_CU.getDelimiter()
  139. || handle.charAt(0) == HandleProviderDelimiter.COMPILATIONUNIT.getDelimiter()) {
  140. // it's something like *MyAspect.aj or {MyClass.java. In other words
  141. // it's a file node that's been created with no children and no parent
  142. return backslash + handle.substring(1);
  143. }
  144. return emptyString;
  145. }
  146. public int getLineNumberForHandle(String handle) {
  147. IProgramElement node = AsmManager.getDefault().getHierarchy().getElement(handle);
  148. if (node != null) {
  149. return node.getSourceLocation().getLine();
  150. } else if (handle.charAt(0) == HandleProviderDelimiter.ASPECT_CU.getDelimiter()
  151. || handle.charAt(0) == HandleProviderDelimiter.COMPILATIONUNIT.getDelimiter()) {
  152. // it's something like *MyAspect.aj or {MyClass.java. In other words
  153. // it's a file node that's been created with no children and no parent
  154. return 1;
  155. }
  156. return -1;
  157. }
  158. public int getOffSetForHandle(String handle) {
  159. IProgramElement node = AsmManager.getDefault().getHierarchy().getElement(handle);
  160. if (node != null) {
  161. return node.getSourceLocation().getOffset();
  162. } else if (handle.charAt(0) == HandleProviderDelimiter.ASPECT_CU.getDelimiter()
  163. || handle.charAt(0) == HandleProviderDelimiter.COMPILATIONUNIT.getDelimiter()) {
  164. // it's something like *MyAspect.aj or {MyClass.java. In other words
  165. // it's a file node that's been created with no children and no parent
  166. return 0;
  167. }
  168. return -1;
  169. }
  170. public String createHandleIdentifier(ISourceLocation location) {
  171. IProgramElement node = AsmManager.getDefault().getHierarchy().findElementForSourceLine(location);
  172. if (node != null) {
  173. return createHandleIdentifier(node);
  174. }
  175. return null;
  176. }
  177. public String createHandleIdentifier(File sourceFile, int line, int column, int offset) {
  178. IProgramElement node = AsmManager.getDefault().getHierarchy().findElementForOffSet(sourceFile.getAbsolutePath(),line,offset);
  179. if (node != null) {
  180. return createHandleIdentifier(node);
  181. }
  182. return null;
  183. }
  184. public boolean dependsOnLocation() {
  185. // handles are independent of soureLocations therefore return false
  186. return false;
  187. }
  188. public void initialize() {
  189. // reset the initializer count. This ensures we return the
  190. // same handle as JDT for initializers.
  191. initializerCounter = 0;
  192. }
  193. }