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.

AsmElementFormatter.java 16KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  1. /* *******************************************************************
  2. * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
  3. * All rights reserved.
  4. * This program and the accompanying materials are made available
  5. * under the terms of the Eclipse Public License v1.0
  6. * which accompanies this distribution and is available at
  7. * http://www.eclipse.org/legal/epl-v10.html
  8. *
  9. * Contributors:
  10. * PARC initial implementation
  11. * Alexandre Vasseur support for @AJ style
  12. * ******************************************************************/
  13. package org.aspectj.ajdt.internal.core.builder;
  14. import java.util.ArrayList;
  15. import java.util.Collections;
  16. import java.util.List;
  17. import org.aspectj.ajdt.internal.compiler.ast.AdviceDeclaration;
  18. import org.aspectj.ajdt.internal.compiler.ast.DeclareDeclaration;
  19. import org.aspectj.ajdt.internal.compiler.ast.InterTypeConstructorDeclaration;
  20. import org.aspectj.ajdt.internal.compiler.ast.InterTypeDeclaration;
  21. import org.aspectj.ajdt.internal.compiler.ast.InterTypeFieldDeclaration;
  22. import org.aspectj.ajdt.internal.compiler.ast.InterTypeMethodDeclaration;
  23. import org.aspectj.ajdt.internal.compiler.ast.PointcutDeclaration;
  24. import org.aspectj.ajdt.internal.compiler.lookup.AjLookupEnvironment;
  25. import org.aspectj.ajdt.internal.compiler.lookup.EclipseFactory;
  26. import org.aspectj.asm.IProgramElement;
  27. import org.aspectj.org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
  28. import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Annotation;
  29. import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Argument;
  30. import org.aspectj.org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
  31. import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeReference;
  32. import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
  33. import org.aspectj.weaver.AdviceKind;
  34. import org.aspectj.weaver.ResolvedType;
  35. import org.aspectj.weaver.UnresolvedType;
  36. import org.aspectj.weaver.patterns.AndPointcut;
  37. import org.aspectj.weaver.patterns.DeclareAnnotation;
  38. import org.aspectj.weaver.patterns.DeclareErrorOrWarning;
  39. import org.aspectj.weaver.patterns.DeclareParents;
  40. import org.aspectj.weaver.patterns.DeclarePrecedence;
  41. import org.aspectj.weaver.patterns.DeclareSoft;
  42. import org.aspectj.weaver.patterns.OrPointcut;
  43. import org.aspectj.weaver.patterns.ReferencePointcut;
  44. import org.aspectj.weaver.patterns.TypePattern;
  45. import org.aspectj.weaver.patterns.TypePatternList;
  46. /**
  47. * @author Mik Kersten
  48. */
  49. public class AsmElementFormatter {
  50. public static final String UNDEFINED="<undefined>";
  51. public static final String DECLARE_PRECEDENCE = "precedence";
  52. public static final String DECLARE_SOFT = "soft";
  53. public static final String DECLARE_PARENTS = "parents";
  54. public static final String DECLARE_WARNING = "warning";
  55. public static final String DECLARE_ERROR = "error";
  56. public static final String DECLARE_UNKNONWN = "<unknown declare>";
  57. public static final String POINTCUT_ABSTRACT = "<abstract pointcut>";
  58. public static final String POINTCUT_ANONYMOUS = "<anonymous pointcut>";
  59. public static final String DOUBLE_DOTS = "..";
  60. public static final int MAX_MESSAGE_LENGTH = 18;
  61. public static final String DEC_LABEL = "declare";
  62. public void genLabelAndKind(MethodDeclaration methodDeclaration, IProgramElement node) {
  63. if (methodDeclaration instanceof AdviceDeclaration) {
  64. AdviceDeclaration ad = (AdviceDeclaration)methodDeclaration;
  65. node.setKind(IProgramElement.Kind.ADVICE);
  66. if (ad.kind == AdviceKind.Around) {
  67. node.setCorrespondingType(ad.returnType.toString()); //returnTypeToString(0));
  68. }
  69. StringBuffer details = new StringBuffer();
  70. if (ad.pointcutDesignator != null) {
  71. if (ad.pointcutDesignator.getPointcut() instanceof ReferencePointcut) {
  72. ReferencePointcut rp = (ReferencePointcut)ad.pointcutDesignator.getPointcut();
  73. details.append(rp.name).append("..");
  74. } else if (ad.pointcutDesignator.getPointcut() instanceof AndPointcut) {
  75. AndPointcut ap = (AndPointcut)ad.pointcutDesignator.getPointcut();
  76. if (ap.getLeft() instanceof ReferencePointcut) {
  77. details.append(ap.getLeft().toString()).append(DOUBLE_DOTS);
  78. } else {
  79. details.append(POINTCUT_ANONYMOUS).append(DOUBLE_DOTS);
  80. }
  81. } else if (ad.pointcutDesignator.getPointcut() instanceof OrPointcut) {
  82. OrPointcut op = (OrPointcut)ad.pointcutDesignator.getPointcut();
  83. if (op.getLeft() instanceof ReferencePointcut) {
  84. details.append(op.getLeft().toString()).append(DOUBLE_DOTS);
  85. } else {
  86. details.append(POINTCUT_ANONYMOUS).append(DOUBLE_DOTS);
  87. }
  88. } else {
  89. details.append(POINTCUT_ANONYMOUS);
  90. }
  91. } else {
  92. details.append(POINTCUT_ABSTRACT);
  93. }
  94. node.setName(ad.kind.toString());
  95. //if (details.length()!=0)
  96. node.setDetails(details.toString());
  97. setParameters(methodDeclaration, node);
  98. } else if (methodDeclaration instanceof PointcutDeclaration) {
  99. PointcutDeclaration pd = (PointcutDeclaration)methodDeclaration;
  100. node.setKind(IProgramElement.Kind.POINTCUT);
  101. node.setName(translatePointcutName(new String(methodDeclaration.selector)));
  102. setParameters(methodDeclaration, node);
  103. } else if (methodDeclaration instanceof DeclareDeclaration) {
  104. DeclareDeclaration declare = (DeclareDeclaration)methodDeclaration;
  105. String name = DEC_LABEL + " ";
  106. if (declare.declareDecl instanceof DeclareErrorOrWarning) {
  107. DeclareErrorOrWarning deow = (DeclareErrorOrWarning)declare.declareDecl;
  108. if (deow.isError()) {
  109. node.setKind( IProgramElement.Kind.DECLARE_ERROR);
  110. name += DECLARE_ERROR;
  111. } else {
  112. node.setKind( IProgramElement.Kind.DECLARE_WARNING);
  113. name += DECLARE_WARNING;
  114. }
  115. node.setName(name) ;
  116. node.setDetails("\"" + genDeclareMessage(deow.getMessage()) + "\"");
  117. } else if (declare.declareDecl instanceof DeclareParents) {
  118. node.setKind( IProgramElement.Kind.DECLARE_PARENTS);
  119. DeclareParents dp = (DeclareParents)declare.declareDecl;
  120. node.setName(name + DECLARE_PARENTS);
  121. String kindOfDP = null;
  122. StringBuffer details = new StringBuffer("");
  123. TypePattern[] newParents = dp.getParents().getTypePatterns();
  124. for (int i = 0; i < newParents.length; i++) {
  125. TypePattern tp = newParents[i];
  126. UnresolvedType tx = tp.getExactType();
  127. if (kindOfDP == null) {
  128. kindOfDP = "implements ";
  129. try {
  130. ResolvedType rtx = tx.resolve(((AjLookupEnvironment)declare.scope.environment()).factory.getWorld());
  131. if (!rtx.isInterface()) kindOfDP = "extends ";
  132. } catch (Throwable t) {
  133. // What can go wrong???? who knows!
  134. }
  135. }
  136. String typename= tp.toString();
  137. if (typename.lastIndexOf(".")!=-1) {
  138. typename=typename.substring(typename.lastIndexOf(".")+1);
  139. }
  140. details.append(typename);
  141. if ((i+1)<newParents.length) details.append(",");
  142. }
  143. node.setDetails(kindOfDP+details.toString());
  144. } else if (declare.declareDecl instanceof DeclareSoft) {
  145. node.setKind( IProgramElement.Kind.DECLARE_SOFT);
  146. DeclareSoft ds = (DeclareSoft)declare.declareDecl;
  147. node.setName(name + DECLARE_SOFT);
  148. node.setDetails(genTypePatternLabel(ds.getException()));
  149. } else if (declare.declareDecl instanceof DeclarePrecedence) {
  150. node.setKind( IProgramElement.Kind.DECLARE_PRECEDENCE);
  151. DeclarePrecedence ds = (DeclarePrecedence)declare.declareDecl;
  152. node.setName(name + DECLARE_PRECEDENCE);
  153. node.setDetails(genPrecedenceListLabel(ds.getPatterns()));
  154. } else if (declare.declareDecl instanceof DeclareAnnotation) {
  155. DeclareAnnotation deca = (DeclareAnnotation)declare.declareDecl;
  156. String thekind = deca.getKind().toString();
  157. node.setName(name+"@"+thekind.substring(3));
  158. if (deca.getKind()==DeclareAnnotation.AT_CONSTRUCTOR) {
  159. node.setKind(IProgramElement.Kind.DECLARE_ANNOTATION_AT_CONSTRUCTOR);
  160. } else if (deca.getKind()==DeclareAnnotation.AT_FIELD) {
  161. node.setKind(IProgramElement.Kind.DECLARE_ANNOTATION_AT_FIELD);
  162. } else if (deca.getKind()==DeclareAnnotation.AT_METHOD) {
  163. node.setKind(IProgramElement.Kind.DECLARE_ANNOTATION_AT_METHOD);
  164. } else if (deca.getKind()==DeclareAnnotation.AT_TYPE) {
  165. node.setKind(IProgramElement.Kind.DECLARE_ANNOTATION_AT_TYPE);
  166. }
  167. node.setDetails(genDecaLabel(deca));
  168. } else {
  169. node.setKind(IProgramElement.Kind.ERROR);
  170. node.setName(DECLARE_UNKNONWN);
  171. }
  172. } else if (methodDeclaration instanceof InterTypeDeclaration) {
  173. InterTypeDeclaration itd = (InterTypeDeclaration)methodDeclaration;
  174. String name = itd.getOnType().toString() + "." + new String(itd.getDeclaredSelector());
  175. if (methodDeclaration instanceof InterTypeFieldDeclaration) {
  176. node.setKind(IProgramElement.Kind.INTER_TYPE_FIELD);
  177. node.setName(name);
  178. } else if (methodDeclaration instanceof InterTypeMethodDeclaration) {
  179. node.setKind(IProgramElement.Kind.INTER_TYPE_METHOD);
  180. node.setName(name);
  181. } else if (methodDeclaration instanceof InterTypeConstructorDeclaration) {
  182. node.setKind(IProgramElement.Kind.INTER_TYPE_CONSTRUCTOR);
  183. // StringBuffer argumentsSignature = new StringBuffer("fubar");
  184. // argumentsSignature.append("(");
  185. // if (methodDeclaration.arguments!=null && methodDeclaration.arguments.length>1) {
  186. //
  187. // for (int i = 1;i<methodDeclaration.arguments.length;i++) {
  188. // argumentsSignature.append(methodDeclaration.arguments[i]);
  189. // if (i+1<methodDeclaration.arguments.length) argumentsSignature.append(",");
  190. // }
  191. // }
  192. // argumentsSignature.append(")");
  193. // InterTypeConstructorDeclaration itcd = (InterTypeConstructorDeclaration)methodDeclaration;
  194. node.setName(itd.getOnType().toString() + "." + itd.getOnType().toString()/*+argumentsSignature.toString()*/);
  195. } else {
  196. node.setKind(IProgramElement.Kind.ERROR);
  197. node.setName(name);
  198. }
  199. node.setCorrespondingType(itd.returnType.toString());
  200. if (node.getKind() != IProgramElement.Kind.INTER_TYPE_FIELD) {
  201. setParameters(methodDeclaration, node);
  202. }
  203. } else {
  204. if (methodDeclaration.isConstructor()) {
  205. node.setKind(IProgramElement.Kind.CONSTRUCTOR);
  206. } else {
  207. node.setKind(IProgramElement.Kind.METHOD);
  208. //TODO AV - could speed up if we could dig only for @Aspect declaring types (or aspect if mixed style allowed)
  209. //??? how to : node.getParent().getKind().equals(IProgramElement.Kind.ASPECT)) {
  210. if (true && methodDeclaration!=null && methodDeclaration.annotations != null && methodDeclaration.scope!=null) {
  211. for (int i = 0; i < methodDeclaration.annotations.length; i++) {
  212. //Note: AV: implicit single advice type support here (should be enforced somewhere as well (APT etc))
  213. Annotation annotation = methodDeclaration.annotations[i];
  214. String annotationSig = new String(annotation.type.getTypeBindingPublic(methodDeclaration.scope).signature());
  215. if (annotationSig!=null && annotationSig.charAt(1)=='o') {
  216. if ("Lorg/aspectj/lang/annotation/Pointcut;".equals(annotationSig)) {
  217. node.setKind(IProgramElement.Kind.POINTCUT);
  218. break;
  219. } else if ("Lorg/aspectj/lang/annotation/Before;".equals(annotationSig)
  220. || "Lorg/aspectj/lang/annotation/After;".equals(annotationSig)
  221. || "Lorg/aspectj/lang/annotation/AfterReturning;".equals(annotationSig)
  222. || "Lorg/aspectj/lang/annotation/AfterThrowing;".equals(annotationSig)
  223. || "Lorg/aspectj/lang/annotation/Around;".equals(annotationSig)) {
  224. node.setKind(IProgramElement.Kind.ADVICE);
  225. //TODO AV - all are considered anonymous - is that ok?
  226. node.setDetails(POINTCUT_ANONYMOUS);
  227. break;
  228. }
  229. }
  230. }
  231. }
  232. }
  233. node.setName(new String(methodDeclaration.selector));
  234. setParameters(methodDeclaration, node);
  235. }
  236. }
  237. private String genDecaLabel(DeclareAnnotation deca) {
  238. StringBuffer sb = new StringBuffer("");
  239. sb.append(deca.getPatternAsString());
  240. sb.append(" : ");
  241. sb.append(deca.getAnnotationString());
  242. return sb.toString();
  243. }
  244. private String genPrecedenceListLabel(TypePatternList list) {
  245. String tpList = "";
  246. for (int i = 0; i < list.size(); i++) {
  247. tpList += genTypePatternLabel(list.get(i));
  248. if (i < list.size()-1) tpList += ", ";
  249. }
  250. return tpList;
  251. }
  252. // private String genArguments(MethodDeclaration md) {
  253. // String args = "";
  254. // Argument[] argArray = md.arguments;
  255. // if (argArray == null) return args;
  256. // for (int i = 0; i < argArray.length; i++) {
  257. // String argName = new String(argArray[i].name);
  258. // String argType = argArray[i].type.toString();
  259. // if (acceptArgument(argName, argType)) {
  260. // args += argType + ", ";
  261. // }
  262. // }
  263. // int lastSepIndex = args.lastIndexOf(',');
  264. // if (lastSepIndex != -1 && args.endsWith(", ")) args = args.substring(0, lastSepIndex);
  265. // return args;
  266. // }
  267. public void setParameters(AbstractMethodDeclaration md, IProgramElement pe) {
  268. Argument[] argArray = md.arguments;
  269. if (argArray == null) {
  270. pe.setParameterNames(Collections.EMPTY_LIST);
  271. pe.setParameterSignatures(Collections.EMPTY_LIST);
  272. } else {
  273. List names = new ArrayList();
  274. List paramSigs = new ArrayList();
  275. for (int i = 0; i < argArray.length; i++) {
  276. String argName = new String(argArray[i].name);
  277. //String argType = "<UnknownType>"; // pr135052
  278. if (acceptArgument(argName, argArray[i].type.toString())) {
  279. TypeReference typeR = argArray[i].type;
  280. if (typeR!=null) {
  281. TypeBinding typeB = typeR.resolvedType;
  282. if (typeB==null) {
  283. typeB = typeR.resolveType(md.scope);
  284. }
  285. EclipseFactory factory = EclipseFactory.fromScopeLookupEnvironment(md.scope);
  286. UnresolvedType ut = factory.fromBinding(typeB);
  287. paramSigs.add(ut.getSignature().toCharArray());
  288. }
  289. names.add(argName);
  290. }
  291. }
  292. pe.setParameterNames(names);
  293. if (!paramSigs.isEmpty()) {
  294. pe.setParameterSignatures(paramSigs);
  295. }
  296. }
  297. }
  298. // TODO: fix this way of determing ajc-added arguments, make subtype of Argument with extra info
  299. private boolean acceptArgument(String name, String type) {
  300. if (name.charAt(0)!='a' && type.charAt(0)!='o') return true;
  301. return !name.startsWith("ajc$this_")
  302. && !type.equals("org.aspectj.lang.JoinPoint.StaticPart")
  303. && !type.equals("org.aspectj.lang.JoinPoint")
  304. && !type.equals("org.aspectj.runtime.internal.AroundClosure");
  305. }
  306. public String genTypePatternLabel(TypePattern tp) {
  307. final String TYPE_PATTERN_LITERAL = "<type pattern>";
  308. String label;
  309. UnresolvedType typeX = tp.getExactType();
  310. if (!ResolvedType.isMissing(typeX)) {
  311. label = typeX.getName();
  312. if (tp.isIncludeSubtypes()) label += "+";
  313. } else {
  314. label = TYPE_PATTERN_LITERAL;
  315. }
  316. return label;
  317. }
  318. public String genDeclareMessage(String message) {
  319. int length = message.length();
  320. if (length < MAX_MESSAGE_LENGTH) {
  321. return message;
  322. } else {
  323. return message.substring(0, MAX_MESSAGE_LENGTH-1) + "..";
  324. }
  325. }
  326. // // TODO:
  327. // private String translateAdviceName(String label) {
  328. // if (label.indexOf("before") != -1) return "before";
  329. // if (label.indexOf("returning") != -1) return "after returning";
  330. // if (label.indexOf("after") != -1) return "after";
  331. // if (label.indexOf("around") != -1) return "around";
  332. // else return "<advice>";
  333. // }
  334. // // !!! move or replace
  335. // private String translateDeclareName(String name) {
  336. // int colonIndex = name.indexOf(":");
  337. // if (colonIndex != -1) {
  338. // return name.substring(0, colonIndex);
  339. // } else {
  340. // return name;
  341. // }
  342. // }
  343. // !!! move or replace
  344. // private String translateInterTypeDecName(String name) {
  345. // int index = name.lastIndexOf('$');
  346. // if (index != -1) {
  347. // return name.substring(index+1);
  348. // } else {
  349. // return name;
  350. // }
  351. // }
  352. // !!! move or replace
  353. private String translatePointcutName(String name) {
  354. int index = name.indexOf("$$")+2;
  355. int endIndex = name.lastIndexOf('$');
  356. if (index != -1 && endIndex != -1) {
  357. return name.substring(index, endIndex);
  358. } else {
  359. return name;
  360. }
  361. }
  362. }