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.

AsmHierarchyBuilder.java 46KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216
  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. * Mik Kersten revisions, added additional relationships
  12. * Alexandre Vasseur support for @AJ style
  13. * ******************************************************************/
  14. package org.aspectj.ajdt.internal.core.builder;
  15. import java.io.File;
  16. import java.io.IOException;
  17. import java.util.ArrayList;
  18. import java.util.Arrays;
  19. import java.util.Iterator;
  20. import java.util.List;
  21. import java.util.ListIterator;
  22. import java.util.Stack;
  23. import java.util.StringTokenizer;
  24. import org.aspectj.ajdt.internal.compiler.CompilationResultDestinationManager;
  25. import org.aspectj.ajdt.internal.compiler.ast.AdviceDeclaration;
  26. import org.aspectj.ajdt.internal.compiler.ast.AspectDeclaration;
  27. import org.aspectj.ajdt.internal.compiler.ast.DeclareDeclaration;
  28. import org.aspectj.ajdt.internal.compiler.ast.InterTypeDeclaration;
  29. import org.aspectj.ajdt.internal.compiler.ast.InterTypeFieldDeclaration;
  30. import org.aspectj.ajdt.internal.compiler.ast.PointcutDeclaration;
  31. import org.aspectj.ajdt.internal.compiler.lookup.AjLookupEnvironment;
  32. import org.aspectj.ajdt.internal.compiler.lookup.EclipseFactory;
  33. import org.aspectj.asm.AsmManager;
  34. import org.aspectj.asm.IProgramElement;
  35. import org.aspectj.asm.internal.CharOperation;
  36. import org.aspectj.asm.internal.ProgramElement;
  37. import org.aspectj.bridge.ISourceLocation;
  38. import org.aspectj.bridge.SourceLocation;
  39. import org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor;
  40. import org.aspectj.org.eclipse.jdt.internal.compiler.CompilationResult;
  41. import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ASTNode;
  42. import org.aspectj.org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
  43. import org.aspectj.org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration;
  44. import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Annotation;
  45. import org.aspectj.org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
  46. import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
  47. import org.aspectj.org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
  48. import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ImportReference;
  49. import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Initializer;
  50. import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Literal;
  51. import org.aspectj.org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
  52. import org.aspectj.org.eclipse.jdt.internal.compiler.ast.OperatorExpression;
  53. import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Reference;
  54. import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
  55. import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeParameter;
  56. import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope;
  57. import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ClassScope;
  58. import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope;
  59. import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.MethodScope;
  60. import org.aspectj.org.eclipse.jdt.internal.compiler.util.Util;
  61. import org.aspectj.util.LangUtil;
  62. import org.aspectj.weaver.BCException;
  63. import org.aspectj.weaver.Member;
  64. import org.aspectj.weaver.ResolvedMember;
  65. import org.aspectj.weaver.ResolvedType;
  66. import org.aspectj.weaver.UnresolvedType;
  67. import org.aspectj.weaver.World;
  68. import org.aspectj.weaver.patterns.AndPointcut;
  69. import org.aspectj.weaver.patterns.Declare;
  70. import org.aspectj.weaver.patterns.DeclareAnnotation;
  71. import org.aspectj.weaver.patterns.DeclareParents;
  72. import org.aspectj.weaver.patterns.OrPointcut;
  73. import org.aspectj.weaver.patterns.Pointcut;
  74. import org.aspectj.weaver.patterns.ReferencePointcut;
  75. import org.aspectj.weaver.patterns.TypePatternList;
  76. /**
  77. * At each iteration of <CODE>processCompilationUnit</CODE> the declarations for a particular compilation unit are added to the
  78. * hierarchy passed as a a parameter.
  79. * <p>
  80. * Clients who extend this class need to ensure that they do not override any of the existing behavior. If they do, the structure
  81. * model will not be built properly and tools such as IDE structure views and ajdoc will fail.
  82. * <p>
  83. * <b>Note:</b> this class is not considered public API and the overridable methods are subject to change.
  84. *
  85. * @author Mik Kersten
  86. */
  87. public class AsmHierarchyBuilder extends ASTVisitor {
  88. protected AsmElementFormatter formatter = new AsmElementFormatter();
  89. // pr148027 - stop generating uses pointcut/pointcut used by relationship
  90. // until we do it in the same way as other relationships.
  91. // public static boolean shouldAddUsesPointcut = false;
  92. /**
  93. * Reset for every compilation unit.
  94. */
  95. protected AjBuildConfig buildConfig;
  96. /**
  97. * Reset for every compilation unit.
  98. */
  99. protected Stack<IProgramElement> stack;
  100. protected ImportReference packageDecl = null;
  101. /**
  102. * Reset for every compilation unit.
  103. */
  104. private CompilationResult currCompilationResult;
  105. private String filename;
  106. int[] lineseps;
  107. /**
  108. *
  109. * @param cuDeclaration
  110. * @param buildConfig
  111. * @param structureModel
  112. * hiearchy to add this unit's declarations to
  113. */
  114. public void buildStructureForCompilationUnit(CompilationUnitDeclaration cuDeclaration, AsmManager structureModel,
  115. AjBuildConfig buildConfig) {
  116. currCompilationResult = cuDeclaration.compilationResult();
  117. filename = new String(currCompilationResult.fileName);
  118. lineseps = currCompilationResult.lineSeparatorPositions;
  119. LangUtil.throwIaxIfNull(currCompilationResult, "result");
  120. stack = new Stack();
  121. packageDecl = null;
  122. this.buildConfig = buildConfig;
  123. internalBuild(cuDeclaration, structureModel);
  124. this.buildConfig = null; // clear reference since this structure is
  125. // anchored in static
  126. currCompilationResult = null;
  127. stack.clear();
  128. // throw new RuntimeException("not implemented");
  129. }
  130. private void internalBuild(CompilationUnitDeclaration unit, AsmManager structureModel) {
  131. LangUtil.throwIaxIfNull(structureModel, "structureModel");
  132. try {
  133. activeStructureModel = structureModel;
  134. // if (!currCompilationResult.equals(unit.compilationResult())) {
  135. // throw new IllegalArgumentException("invalid unit: " + unit);
  136. // }
  137. // ---- summary
  138. // add unit to package (or root if no package),
  139. // first removing any duplicate (XXX? removes children if 3 classes in
  140. // same file?)
  141. // push the node on the stack
  142. // and traverse
  143. // -- create node to add
  144. final File file = new File(new String(unit.getFileName()));
  145. final IProgramElement cuNode;
  146. {
  147. // AMC - use the source start and end from the compilation unit decl
  148. int startLine = getStartLine(unit);
  149. int endLine = getEndLine(unit);
  150. SourceLocation sourceLocation = new SourceLocation(file, startLine, endLine);
  151. sourceLocation.setOffset(unit.sourceStart);
  152. cuNode = new ProgramElement(structureModel, new String(file.getName()), IProgramElement.Kind.FILE_JAVA,
  153. sourceLocation, 0, null, null);
  154. }
  155. // container for import declarations - this may move to position 1 in the child list, if there
  156. // is a package declaration
  157. cuNode.addChild(new ProgramElement(structureModel, "", IProgramElement.Kind.IMPORT_REFERENCE, null, 0, null, null));
  158. final IProgramElement addToNode = genAddToNode(file, unit, structureModel);
  159. // -- remove duplicates before adding (XXX use them instead?)
  160. if (addToNode != null && addToNode.getChildren() != null) {
  161. for (ListIterator itt = addToNode.getChildren().listIterator(); itt.hasNext();) {
  162. IProgramElement child = (IProgramElement) itt.next();
  163. ISourceLocation childLoc = child.getSourceLocation();
  164. if (null == childLoc) {
  165. // XXX ok, packages have null source locations
  166. // signal others?
  167. } else if (childLoc.getSourceFile().equals(file)) {
  168. itt.remove();
  169. }
  170. }
  171. }
  172. // -- add and traverse
  173. addToNode.addChild(cuNode);
  174. stack.push(cuNode);
  175. unit.traverse(this, unit.scope);
  176. // -- update file map (XXX do this before traversal?)
  177. try {
  178. structureModel.getHierarchy().addToFileMap(file.getCanonicalPath(), cuNode);
  179. } catch (IOException e) {
  180. System.err.println("IOException " + e.getMessage() + " creating path for " + file);
  181. // XXX signal IOException when canonicalizing file path
  182. }
  183. } finally {
  184. activeStructureModel = null;
  185. }
  186. }
  187. private AsmManager activeStructureModel = null;
  188. private IProgramElement findOrCreateChildSourceFolder(String sourceFolder, AsmManager structureModel) {
  189. IProgramElement root = structureModel.getHierarchy().getRoot();
  190. // Check if already there
  191. IProgramElement sourceFolderNode = null;
  192. List<IProgramElement> kids = root.getChildren();
  193. for (IProgramElement child : kids) {
  194. if (child.getKind() == IProgramElement.Kind.SOURCE_FOLDER && child.getName().equals(sourceFolder)) {
  195. sourceFolderNode = child;
  196. break;
  197. }
  198. }
  199. if (sourceFolderNode == null) {
  200. sourceFolderNode = new ProgramElement(structureModel, sourceFolder, IProgramElement.Kind.SOURCE_FOLDER, new ArrayList());
  201. root.addChild(sourceFolderNode);
  202. }
  203. return sourceFolderNode;
  204. }
  205. /**
  206. * Get/create the node (package or root) to add to.
  207. */
  208. private IProgramElement genAddToNode(File sourceFile, CompilationUnitDeclaration unit, AsmManager structureModel) {
  209. final IProgramElement addToNode;
  210. {
  211. CompilationResultDestinationManager manager = buildConfig.getCompilationResultDestinationManager();
  212. String sourceFolder = (manager == null ? null : manager.getSourceFolderForFile(sourceFile));
  213. ImportReference unitPackage = unit.currentPackage;
  214. // if (null == unitPackage) {
  215. // // Is there a sourceFolder to stick in?
  216. // if (sourceFolder == null) {
  217. // addToNode = structureModel.getRoot();
  218. // } else {
  219. // addToNode = findOrCreateChildSourceFolder(sourceFolder, structureModel);
  220. // }
  221. // } else {
  222. IProgramElement rootForSource = structureModel.getHierarchy().getRoot();
  223. if (sourceFolder != null) {
  224. rootForSource = findOrCreateChildSourceFolder(sourceFolder, structureModel);
  225. }
  226. String pkgName;
  227. if (unitPackage == null) {
  228. pkgName = "";
  229. } else {
  230. StringBuffer nameBuffer = new StringBuffer();
  231. final char[][] importName = unitPackage.getImportName();
  232. final int last = importName.length - 1;
  233. for (int i = 0; i < importName.length; i++) {
  234. nameBuffer.append(new String(importName[i]));
  235. if (i < last) {
  236. nameBuffer.append('.');
  237. }
  238. }
  239. pkgName = nameBuffer.toString();
  240. }
  241. IProgramElement pkgNode = null;
  242. if (structureModel != null && structureModel.getHierarchy().getRoot() != null && rootForSource.getChildren() != null) {
  243. for (IProgramElement currNode : rootForSource.getChildren()) {
  244. if (pkgName.equals(currNode.getName())) {
  245. pkgNode = currNode;
  246. break;
  247. }
  248. }
  249. }
  250. if (pkgNode == null) {
  251. // note packages themselves have no source location
  252. pkgNode = new ProgramElement(activeStructureModel, pkgName, IProgramElement.Kind.PACKAGE, new ArrayList());
  253. rootForSource.addChild(pkgNode);
  254. }
  255. addToNode = pkgNode;
  256. // }
  257. }
  258. return addToNode;
  259. }
  260. public boolean visit(TypeDeclaration typeDeclaration, CompilationUnitScope scope) {
  261. String name = new String(typeDeclaration.name);
  262. IProgramElement.Kind kind = IProgramElement.Kind.CLASS;
  263. if (typeDeclaration instanceof AspectDeclaration) {
  264. kind = IProgramElement.Kind.ASPECT;
  265. } else if (TypeDeclaration.kind(typeDeclaration.modifiers) == TypeDeclaration.INTERFACE_DECL) {
  266. kind = IProgramElement.Kind.INTERFACE;
  267. } else if (TypeDeclaration.kind(typeDeclaration.modifiers) == TypeDeclaration.ENUM_DECL) {
  268. kind = IProgramElement.Kind.ENUM;
  269. } else if (TypeDeclaration.kind(typeDeclaration.modifiers) == TypeDeclaration.ANNOTATION_TYPE_DECL) {
  270. kind = IProgramElement.Kind.ANNOTATION;
  271. }
  272. boolean isAnnotationStyleAspect = false;
  273. // @AJ support
  274. if (typeDeclaration.annotations != null) {
  275. for (int i = 0; i < typeDeclaration.annotations.length; i++) {
  276. Annotation annotation = typeDeclaration.annotations[i];
  277. if (Arrays.equals(annotation.type.getTypeBindingPublic(scope).signature(),
  278. "Lorg/aspectj/lang/annotation/Aspect;".toCharArray())) {
  279. kind = IProgramElement.Kind.ASPECT;
  280. if (!(typeDeclaration instanceof AspectDeclaration)) {
  281. isAnnotationStyleAspect = true;
  282. }
  283. } else if (annotation.resolvedType != null) {
  284. // Fix for the case where in a privileged aspect a parent declaration :
  285. // declare parents: (@A C+) implements (B);
  286. // is causing the resolvedType to be null when it shouldn't
  287. // for the aspect and privileged annotation of that aspect.
  288. // Creating the char[][] needed for ImportReference
  289. String[] temp = (new String(annotation.resolvedType.constantPoolName())).split("/");
  290. if (temp.length > 1) {
  291. char[][] path = new char[temp.length][];
  292. for (int k = 0; k < temp.length; k++) {
  293. path[k] = temp[k].toCharArray();
  294. }
  295. // Create the ImportReference needed to add a
  296. // ProgramElement
  297. ImportReference importRef = new ImportReference(path, new long[] { 0 }, false, 0);
  298. IProgramElement ceNode = new ProgramElement(activeStructureModel, importRef.toString(),
  299. IProgramElement.Kind.IMPORT_REFERENCE, makeLocation(importRef), 0, null, null);
  300. ceNode.setSourceSignature(genSourceSignature(importRef));
  301. // Add Element to Imports of Current Class
  302. ProgramElement imports = getImportReferencesRoot();// (ProgramElement) ((IProgramElement)
  303. // stack.peek()).getChildren().get(0);
  304. imports.addChild(0, ceNode);
  305. }
  306. }
  307. }
  308. }
  309. int typeModifiers = typeDeclaration.modifiers;
  310. if (typeDeclaration instanceof AspectDeclaration) {
  311. typeModifiers = ((AspectDeclaration) typeDeclaration).getDeclaredModifiers();
  312. }
  313. IProgramElement peNode = new ProgramElement(activeStructureModel, name, kind, makeLocation(typeDeclaration), typeModifiers,
  314. null, null);
  315. peNode.setSourceSignature(genSourceSignature(typeDeclaration));
  316. peNode.setFormalComment(generateJavadocComment(typeDeclaration));
  317. peNode.setAnnotationStyleDeclaration(isAnnotationStyleAspect);
  318. stack.peek().addChild(peNode);
  319. stack.push(peNode);
  320. return true;
  321. }
  322. public void endVisit(TypeDeclaration typeDeclaration, CompilationUnitScope scope) {
  323. // Is there a package declaration to insert into the model?
  324. if (packageDecl != null) {
  325. int dotIndex = packageDecl.toString().lastIndexOf('.');
  326. String packageString = packageDecl.toString();
  327. ProgramElement packageDeclaration = new ProgramElement(activeStructureModel, packageString,
  328. IProgramElement.Kind.PACKAGE_DECLARATION, makeLocation(packageDecl), 0, null, null);
  329. StringBuffer packageSourceDeclaration = new StringBuffer();
  330. packageSourceDeclaration.append("package ");
  331. packageSourceDeclaration.append(packageString);
  332. packageSourceDeclaration.append(";");
  333. packageDeclaration.setSourceSignature(packageSourceDeclaration.toString());
  334. stack.pop();
  335. ProgramElement containingTypeElement = (ProgramElement) stack.peek();
  336. containingTypeElement.addChild(0, packageDeclaration);
  337. packageDecl = null;
  338. } else {
  339. stack.pop();
  340. }
  341. }
  342. // ??? share impl with visit(TypeDeclaration, ..) ?
  343. public boolean visit(TypeDeclaration memberTypeDeclaration, ClassScope scope) {
  344. String name = new String(memberTypeDeclaration.name);
  345. IProgramElement.Kind kind = IProgramElement.Kind.CLASS;
  346. int typeDeclarationKind = TypeDeclaration.kind(memberTypeDeclaration.modifiers);
  347. if (memberTypeDeclaration instanceof AspectDeclaration) {
  348. kind = IProgramElement.Kind.ASPECT;
  349. } else if (typeDeclarationKind == TypeDeclaration.INTERFACE_DECL) {
  350. kind = IProgramElement.Kind.INTERFACE;
  351. } else if (typeDeclarationKind == TypeDeclaration.ENUM_DECL) {
  352. kind = IProgramElement.Kind.ENUM;
  353. } else if (typeDeclarationKind == TypeDeclaration.ANNOTATION_TYPE_DECL) {
  354. kind = IProgramElement.Kind.ANNOTATION;
  355. }
  356. boolean isAnnotationStyleAspect = false;
  357. // @AJ support
  358. if (memberTypeDeclaration.annotations != null) {
  359. for (int i = 0; i < memberTypeDeclaration.annotations.length; i++) {
  360. Annotation annotation = memberTypeDeclaration.annotations[i];
  361. if (Arrays.equals(annotation.type.getTypeBindingPublic(scope).signature(),
  362. "Lorg/aspectj/lang/annotation/Aspect;".toCharArray())) {
  363. kind = IProgramElement.Kind.ASPECT;
  364. if (!(memberTypeDeclaration instanceof AspectDeclaration)) {
  365. isAnnotationStyleAspect = true;
  366. }
  367. }
  368. }
  369. }
  370. int typeModifiers = memberTypeDeclaration.modifiers;
  371. if (memberTypeDeclaration instanceof AspectDeclaration) {
  372. typeModifiers = ((AspectDeclaration) memberTypeDeclaration).getDeclaredModifiers();
  373. }
  374. IProgramElement peNode = new ProgramElement(activeStructureModel, name, kind, makeLocation(memberTypeDeclaration),
  375. typeModifiers, null, null);
  376. peNode.setSourceSignature(genSourceSignature(memberTypeDeclaration));
  377. peNode.setFormalComment(generateJavadocComment(memberTypeDeclaration));
  378. peNode.setAnnotationStyleDeclaration(isAnnotationStyleAspect);
  379. ((IProgramElement) stack.peek()).addChild(peNode);
  380. stack.push(peNode);
  381. return true;
  382. }
  383. public void endVisit(TypeDeclaration memberTypeDeclaration, ClassScope scope) {
  384. stack.pop();
  385. }
  386. public boolean visit(TypeDeclaration memberTypeDeclaration, BlockScope scope) {
  387. String fullName = "<undefined>";
  388. if (memberTypeDeclaration.allocation != null && memberTypeDeclaration.allocation.type != null) {
  389. // Create a name something like 'new Runnable() {..}'
  390. fullName = "new " + memberTypeDeclaration.allocation.type.toString() + "() {..}";
  391. } else if (memberTypeDeclaration.binding != null && memberTypeDeclaration.binding.constantPoolName() != null) {
  392. // If we couldn't find a nice name like 'new Runnable() {..}' then
  393. // use the number after the $
  394. fullName = new String(memberTypeDeclaration.name);
  395. // fullName = new String(memberTypeDeclaration.binding
  396. // .constantPoolName());
  397. int dollar = fullName.indexOf('$');
  398. fullName = fullName.substring(dollar + 1);
  399. }
  400. IProgramElement.Kind kind = IProgramElement.Kind.CLASS;
  401. if (TypeDeclaration.kind(memberTypeDeclaration.modifiers) == TypeDeclaration.INTERFACE_DECL) {
  402. kind = IProgramElement.Kind.INTERFACE;
  403. } else if (TypeDeclaration.kind(memberTypeDeclaration.modifiers) == TypeDeclaration.ENUM_DECL) {
  404. kind = IProgramElement.Kind.ENUM;
  405. } else if (TypeDeclaration.kind(memberTypeDeclaration.modifiers) == TypeDeclaration.ANNOTATION_TYPE_DECL) {
  406. kind = IProgramElement.Kind.ANNOTATION;
  407. }
  408. // @AJ support
  409. boolean isAnnotationStyleAspect = false;
  410. if (memberTypeDeclaration.annotations != null) {
  411. for (int i = 0; i < memberTypeDeclaration.annotations.length; i++) {
  412. Annotation annotation = memberTypeDeclaration.annotations[i];
  413. if (Arrays.equals(annotation.type.getTypeBindingPublic(scope).signature(),
  414. "Lorg/aspectj/lang/annotation/Aspect;".toCharArray())) {
  415. kind = IProgramElement.Kind.ASPECT;
  416. if (!(memberTypeDeclaration instanceof AspectDeclaration)) {
  417. isAnnotationStyleAspect = true;
  418. }
  419. break;
  420. }
  421. }
  422. }
  423. IProgramElement peNode = new ProgramElement(activeStructureModel, fullName, kind, makeLocation(memberTypeDeclaration),
  424. memberTypeDeclaration.modifiers, null, null);
  425. peNode.setSourceSignature(genSourceSignature(memberTypeDeclaration));
  426. peNode.setFormalComment(generateJavadocComment(memberTypeDeclaration));
  427. peNode.setAnnotationStyleDeclaration(isAnnotationStyleAspect);
  428. // if we're something like 'new Runnable(){..}' then set the
  429. // bytecodeSignature to be the typename so we can match it later
  430. // when creating the structure model
  431. if (peNode.getBytecodeSignature() == null && memberTypeDeclaration.binding != null
  432. && memberTypeDeclaration.binding.constantPoolName() != null) {
  433. StringTokenizer st = new StringTokenizer(new String(memberTypeDeclaration.binding.constantPoolName()), "/");
  434. while (st.hasMoreTokens()) {
  435. String s = st.nextToken();
  436. if (!st.hasMoreTokens()) {
  437. peNode.setBytecodeSignature(s);
  438. }
  439. }
  440. }
  441. IProgramElement ipe = (IProgramElement)stack.peek();
  442. if (ipe!=null) {
  443. // With AspectJ 1.8.9 the type structure must be slightly different as the guard
  444. // is required (the null is due to a default constructor).
  445. ((IProgramElement) stack.peek()).addChild(peNode);
  446. }
  447. stack.push(peNode);
  448. return true;
  449. }
  450. public void endVisit(TypeDeclaration memberTypeDeclaration, BlockScope scope) {
  451. stack.pop();
  452. }
  453. private String genSourceSignature(TypeDeclaration typeDeclaration) {
  454. StringBuffer output = new StringBuffer();
  455. typeDeclaration.printHeader(0, output);
  456. return output.toString();
  457. }
  458. // private IProgramElement findEnclosingClass(Stack stack) {
  459. // for (int i = stack.size() - 1; i >= 0; i--) {
  460. // IProgramElement pe = (IProgramElement) stack.get(i);
  461. // if (pe.getKind() == IProgramElement.Kind.CLASS) {
  462. // return pe;
  463. // }
  464. //
  465. // }
  466. // return (IProgramElement) stack.peek();
  467. // }
  468. public boolean visit(MethodDeclaration methodDeclaration, ClassScope scope) {
  469. IProgramElement peNode = null;
  470. // For intertype decls, use the modifiers from the original signature,
  471. // not the generated method
  472. if (methodDeclaration instanceof InterTypeDeclaration) {
  473. InterTypeDeclaration itd = (InterTypeDeclaration) methodDeclaration;
  474. ResolvedMember sig = itd.getSignature();
  475. peNode = new ProgramElement(activeStructureModel, null, IProgramElement.Kind.ERROR, makeLocation(methodDeclaration),
  476. (sig != null ? sig.getModifiers() : 0), null, null);
  477. } else {
  478. peNode = new ProgramElement(activeStructureModel, null, IProgramElement.Kind.ERROR, makeLocation(methodDeclaration),
  479. methodDeclaration.modifiers, null, null);
  480. }
  481. formatter.genLabelAndKind(methodDeclaration, peNode); // will set the
  482. // name
  483. genBytecodeInfo(methodDeclaration, peNode);
  484. List namedPointcuts = genNamedPointcuts(methodDeclaration);
  485. // if (shouldAddUsesPointcut)
  486. // addUsesPointcutRelationsForNode(peNode, namedPointcuts, methodDeclaration);
  487. if (methodDeclaration instanceof DeclareDeclaration) {
  488. DeclareDeclaration dDeclaration = (DeclareDeclaration) methodDeclaration;
  489. Declare decl = dDeclaration.declareDecl;
  490. if (decl instanceof DeclareParents) {
  491. TypePatternList tpl = ((DeclareParents) decl).getParents();
  492. List<String> parents = new ArrayList<>();
  493. for (int i = 0; i < tpl.size(); i++) {
  494. parents.add(tpl.get(i).getExactType().getName().replaceAll("\\$", "."));
  495. }
  496. peNode.setParentTypes(parents);
  497. }
  498. if (decl instanceof DeclareAnnotation) {
  499. DeclareAnnotation da = (DeclareAnnotation) decl;
  500. ResolvedType annotationType = da.getAnnotationType();
  501. if (annotationType == null) {
  502. String s = ((DeclareAnnotation) decl).getAnnotationString();
  503. if (s != null && s.length() > 0) {
  504. s = s.substring(1);
  505. }
  506. peNode.setAnnotationType(s);
  507. } else {
  508. peNode.setAnnotationType(annotationType.getName());
  509. }
  510. if (da.isRemover()) {
  511. peNode.setAnnotationRemover(true);
  512. }
  513. }
  514. }
  515. if (methodDeclaration.returnType != null) {
  516. // if we don't make the distinction between ITD fields and other
  517. // methods, then we loose the type, for example int, for the field
  518. // and instead get "void".
  519. if (peNode.getKind().equals(IProgramElement.Kind.INTER_TYPE_FIELD)) {
  520. InterTypeFieldDeclaration itfd = (InterTypeFieldDeclaration) methodDeclaration;
  521. if (itfd.getRealFieldType() != null) {
  522. peNode.setCorrespondingType(new String(itfd.getRealFieldType().readableName()));
  523. } else {
  524. peNode.setCorrespondingType(null);
  525. }
  526. // was peNode.setCorrespondingType(methodDeclaration.returnType.toString());
  527. } else {
  528. if (methodDeclaration.returnType.resolvedType != null) {
  529. peNode.setCorrespondingType(new String(methodDeclaration.returnType.resolvedType.readableName()));
  530. } else {
  531. peNode.setCorrespondingType(null);
  532. }
  533. }
  534. } else {
  535. peNode.setCorrespondingType(null);
  536. }
  537. peNode.setSourceSignature(genSourceSignature(methodDeclaration));
  538. peNode.setFormalComment(generateJavadocComment(methodDeclaration));
  539. // TODO: add return type test
  540. if (peNode.getKind().equals(IProgramElement.Kind.METHOD)) {
  541. if ((peNode.getName().charAt(0) == 'm')
  542. && (peNode.toLabelString().equals("main(String[])") || peNode.toLabelString()
  543. .equals("main(java.lang.String[])"))
  544. && peNode.getModifiers().contains(IProgramElement.Modifiers.STATIC)
  545. && peNode.getAccessibility().equals(IProgramElement.Accessibility.PUBLIC)) {
  546. ((IProgramElement) stack.peek()).setRunnable(true);
  547. }
  548. }
  549. stack.push(peNode);
  550. return true;
  551. }
  552. // private void addUsesPointcutRelationsForNode(IProgramElement peNode, List namedPointcuts, MethodDeclaration declaration) {
  553. // for (Iterator it = namedPointcuts.iterator(); it.hasNext();) {
  554. // ReferencePointcut rp = (ReferencePointcut) it.next();
  555. // ResolvedMember member = getPointcutDeclaration(rp, declaration);
  556. // if (member != null) {
  557. // IRelationship foreward = AsmManager.getDefault().getRelationshipMap().get(peNode.getHandleIdentifier(),
  558. // IRelationship.Kind.USES_POINTCUT, "uses pointcut", false, true);
  559. // IProgramElement forwardIPE = AsmManager.getDefault().getHierarchy().findElementForSourceLine(
  560. // member.getSourceLocation());
  561. // foreward.addTarget(AsmManager.getDefault().getHandleProvider().createHandleIdentifier(forwardIPE));
  562. //
  563. // IRelationship back = AsmManager.getDefault().getRelationshipMap().get(
  564. // AsmManager.getDefault().getHandleProvider().createHandleIdentifier(forwardIPE),
  565. // IRelationship.Kind.USES_POINTCUT, "pointcut used by", false, true);
  566. // back.addTarget(peNode.getHandleIdentifier());
  567. // }
  568. // }
  569. // }
  570. private ResolvedMember getPointcutDeclaration(ReferencePointcut rp, MethodDeclaration declaration) {
  571. EclipseFactory factory = ((AjLookupEnvironment) declaration.scope.environment()).factory;
  572. World world = factory.getWorld();
  573. UnresolvedType onType = rp.onType;
  574. if (onType == null) {
  575. if (declaration.binding != null) {
  576. Member member = factory.makeResolvedMember(declaration.binding);
  577. onType = member.getDeclaringType();
  578. } else {
  579. return null;
  580. }
  581. }
  582. ResolvedMember[] members = onType.resolve(world).getDeclaredPointcuts();
  583. if (members != null) {
  584. for (ResolvedMember member : members) {
  585. if (member.getName().equals(rp.name)) {
  586. return member;
  587. }
  588. }
  589. }
  590. return null;
  591. }
  592. /**
  593. * @param methodDeclaration
  594. * @return all of the named pointcuts referenced by the PCD of this declaration
  595. */
  596. private List genNamedPointcuts(MethodDeclaration methodDeclaration) {
  597. List pointcuts = new ArrayList();
  598. if (methodDeclaration instanceof AdviceDeclaration) {
  599. if (((AdviceDeclaration) methodDeclaration).pointcutDesignator != null) {
  600. addAllNamed(((AdviceDeclaration) methodDeclaration).pointcutDesignator.getPointcut(), pointcuts);
  601. }
  602. } else if (methodDeclaration instanceof PointcutDeclaration) {
  603. if (((PointcutDeclaration) methodDeclaration).pointcutDesignator != null) {
  604. addAllNamed(((PointcutDeclaration) methodDeclaration).pointcutDesignator.getPointcut(), pointcuts);
  605. }
  606. }
  607. return pointcuts;
  608. }
  609. /**
  610. * @param left
  611. * @param pointcuts
  612. * accumulator for named pointcuts
  613. */
  614. private void addAllNamed(Pointcut pointcut, List pointcuts) {
  615. if (pointcut == null) {
  616. return;
  617. }
  618. if (pointcut instanceof ReferencePointcut) {
  619. ReferencePointcut rp = (ReferencePointcut) pointcut;
  620. pointcuts.add(rp);
  621. } else if (pointcut instanceof AndPointcut) {
  622. AndPointcut ap = (AndPointcut) pointcut;
  623. addAllNamed(ap.getLeft(), pointcuts);
  624. addAllNamed(ap.getRight(), pointcuts);
  625. } else if (pointcut instanceof OrPointcut) {
  626. OrPointcut op = (OrPointcut) pointcut;
  627. addAllNamed(op.getLeft(), pointcuts);
  628. addAllNamed(op.getRight(), pointcuts);
  629. }
  630. }
  631. private String genSourceSignature(MethodDeclaration methodDeclaration) {
  632. StringBuffer output = new StringBuffer();
  633. ASTNode.printModifiers(methodDeclaration.modifiers, output);
  634. // Append Type Parameters if any
  635. TypeParameter types[] = methodDeclaration.typeParameters();
  636. if (types != null && types.length != 0) {
  637. output.append("<");
  638. for (int i = 0; i < types.length; i++) {
  639. if (i > 0) {
  640. output.append(", ");
  641. }
  642. types[i].printStatement(0, output);
  643. }
  644. output.append("> ");
  645. }
  646. String methodName = methodDeclaration.selector==null?"null":new String(methodDeclaration.selector);
  647. methodDeclaration.printReturnType(0, output).append(methodName).append('(');
  648. if (methodDeclaration.arguments != null) {
  649. for (int i = 0; i < methodDeclaration.arguments.length; i++) {
  650. if (i > 0) {
  651. output.append(", "); //$NON-NLS-1$
  652. }
  653. methodDeclaration.arguments[i].print(0, output);
  654. }
  655. }
  656. output.append(')');
  657. if (methodDeclaration.thrownExceptions != null) {
  658. output.append(" throws "); //$NON-NLS-1$
  659. for (int i = 0; i < methodDeclaration.thrownExceptions.length; i++) {
  660. if (i > 0) {
  661. output.append(", "); //$NON-NLS-1$
  662. }
  663. methodDeclaration.thrownExceptions[i].print(0, output);
  664. }
  665. }
  666. return output.toString();
  667. }
  668. // protected void genBytecodeInfo(MethodDeclaration methodDeclaration,
  669. // IProgramElement peNode) {
  670. // if (methodDeclaration.binding != null) {
  671. // String memberName = "";
  672. // String memberBytecodeSignature = "";
  673. // try {
  674. // EclipseFactory factory =
  675. // ((AjLookupEnvironment)methodDeclaration.scope.environment()).factory;
  676. // Member member = factory.makeResolvedMember(methodDeclaration.binding);
  677. // memberName = member.getName();
  678. // memberBytecodeSignature = member.getSignature();
  679. // } catch (BCException bce) { // bad type name
  680. // memberName = "<undefined>";
  681. // } catch (NullPointerException npe) {
  682. // memberName = "<undefined>";
  683. // }
  684. //
  685. // peNode.setBytecodeName(memberName);
  686. // peNode.setBytecodeSignature(memberBytecodeSignature);
  687. // }
  688. // ((IProgramElement)stack.peek()).addChild(peNode);
  689. // }
  690. protected void genBytecodeInfo(MethodDeclaration methodDeclaration, IProgramElement peNode) {
  691. if (methodDeclaration.binding != null) {
  692. try {
  693. EclipseFactory factory = ((AjLookupEnvironment) methodDeclaration.scope.environment()).factory;
  694. Member member = factory.makeResolvedMember(methodDeclaration.binding);
  695. peNode.setBytecodeName(member.getName());
  696. peNode.setBytecodeSignature(member.getSignature());
  697. } catch (BCException bce) { // bad type name
  698. bce.printStackTrace();
  699. } catch (NullPointerException npe) {
  700. npe.printStackTrace();
  701. }
  702. }
  703. ((IProgramElement) stack.peek()).addChild(peNode);
  704. }
  705. public void endVisit(MethodDeclaration methodDeclaration, ClassScope scope) {
  706. stack.pop();
  707. }
  708. public boolean visit(ImportReference importRef, CompilationUnitScope scope) {
  709. // 3.3 compiler used to represent the package statement in such a way that toString() would return 'foo.*' for 'package foo;'
  710. // 3.7 compiler doesn't create an 'ondemand' import reference so it is purely toString()'d as 'foo'
  711. String currPackageImport = importRef.toString();
  712. String stackPackageName = stack.peek().getPackageName();
  713. if (stackPackageName.equals(currPackageImport)) {
  714. packageDecl = importRef;
  715. } else {
  716. ProgramElement peNode = new ProgramElement(activeStructureModel, new String(importRef.toString()),
  717. IProgramElement.Kind.IMPORT_REFERENCE, makeLocation(importRef), 0,// could set static here, but for
  718. // some reason the info is
  719. // private
  720. null, null);
  721. // set it here instead
  722. if (importRef.isStatic()) {
  723. peNode.addModifiers(IProgramElement.Modifiers.STATIC);
  724. }
  725. // create Source signature for import
  726. peNode.setSourceSignature(genSourceSignature(importRef));
  727. IProgramElement containingTypeElement = (IProgramElement) stack.peek();
  728. ProgramElement imports = getImportReferencesRoot();
  729. imports.addChild(0, peNode);
  730. stack.push(peNode);
  731. }
  732. return true;
  733. }
  734. private ProgramElement getImportReferencesRoot() {
  735. IProgramElement element = (IProgramElement) stack.peek();
  736. boolean hasPackageDeclaration = (element.getChildren().get(0)).getKind().isPackageDeclaration();
  737. return (ProgramElement) element.getChildren().get(hasPackageDeclaration ? 1 : 0);
  738. }
  739. public void endVisit(ImportReference importRef, CompilationUnitScope scope) {
  740. // 3.3 compiler used to represent the package statement in such a way that toString() would return 'foo.*' for 'package foo;'
  741. // 3.7 compiler doesn't create an 'ondemand' import reference so it is purely toString()'d as 'foo'
  742. String currPackageImport = importRef.toString();
  743. if (!stack.peek().getPackageName().equals(currPackageImport)) {
  744. stack.pop();
  745. }
  746. }
  747. private String genSourceSignature(ImportReference importreference) {
  748. StringBuffer output = new StringBuffer();
  749. output.append("import ");
  750. ASTNode.printModifiers(importreference.modifiers, output);
  751. output.append(importreference);
  752. output.append(";");
  753. return output.toString();
  754. }
  755. public boolean visit(FieldDeclaration fieldDeclaration, MethodScope scope) {
  756. IProgramElement peNode = null;
  757. if (fieldDeclaration.type == null) { // The field represents an enum
  758. // value
  759. peNode = new ProgramElement(activeStructureModel, new String(fieldDeclaration.name), IProgramElement.Kind.ENUM_VALUE,
  760. makeLocation(fieldDeclaration), fieldDeclaration.modifiers, null, null);
  761. String type = null;
  762. boolean isOk = true;
  763. if (fieldDeclaration.binding == null) {
  764. type="fieldDeclaration_binding_is_null";
  765. System.err.println("DebugFor402832: null fieldDeclaration.binding for "+fieldDeclaration);
  766. isOk=false;
  767. } else {
  768. if (fieldDeclaration.binding.type==null) {
  769. System.err.println("DebugFor402832: null fieldDeclaration.binding.type for "+fieldDeclaration);
  770. type="fieldDeclaration_binding_type_is_null";
  771. isOk=false;
  772. } else {
  773. type=fieldDeclaration.binding.type.debugName();
  774. }
  775. }
  776. if (!isOk) {
  777. if (fieldDeclaration.type!=null && fieldDeclaration.type.resolvedType!=null) {
  778. type = fieldDeclaration.type.resolvedType.debugName();
  779. System.err.println("DebugFor402832: used secondary route to compute name for "+fieldDeclaration+", set to "+type);
  780. isOk=true;
  781. }
  782. }
  783. peNode.setCorrespondingType(type);
  784. // peNode.setCorrespondingType(fieldDeclaration.binding.type.debugName());
  785. } else {
  786. peNode = new ProgramElement(activeStructureModel, new String(fieldDeclaration.name), IProgramElement.Kind.FIELD,
  787. makeLocation(fieldDeclaration), fieldDeclaration.modifiers, null, null);
  788. if (fieldDeclaration.type.resolvedType != null) {
  789. char[] cs = fieldDeclaration.type.resolvedType.readableName();
  790. // fieldDeclaration.type.resolvedType.genericTypeSignature()
  791. peNode.setCorrespondingType(new String(cs));
  792. } else {
  793. // peNode.setCorrespondingType(null);
  794. peNode.setCorrespondingType(fieldDeclaration.type.toString());
  795. }
  796. }
  797. peNode.setSourceSignature(genSourceSignature(fieldDeclaration));
  798. peNode.setFormalComment(generateJavadocComment(fieldDeclaration));
  799. // peNode.setBytecodeSignature(new String(fieldDeclaration.binding.type.signature()));
  800. ((IProgramElement) stack.peek()).addChild(peNode);
  801. stack.push(peNode);
  802. return true;
  803. }
  804. public void endVisit(FieldDeclaration fieldDeclaration, MethodScope scope) {
  805. stack.pop();
  806. }
  807. /**
  808. * Checks if comments should be added to the model before generating.
  809. */
  810. protected String generateJavadocComment(ASTNode astNode) {
  811. if (buildConfig != null && !buildConfig.isGenerateJavadocsInModelMode()) {
  812. return null;
  813. }
  814. // StringBuffer sb = new StringBuffer(); // !!! specify length?
  815. // boolean completed = false;
  816. int startIndex = -1;
  817. if (astNode instanceof MethodDeclaration) {
  818. startIndex = ((MethodDeclaration) astNode).declarationSourceStart;
  819. } else if (astNode instanceof FieldDeclaration) {
  820. startIndex = ((FieldDeclaration) astNode).declarationSourceStart;
  821. } else if (astNode instanceof TypeDeclaration) {
  822. startIndex = ((TypeDeclaration) astNode).declarationSourceStart;
  823. } else if (astNode instanceof ConstructorDeclaration) {
  824. startIndex = ((ConstructorDeclaration) astNode).declarationSourceStart;
  825. }
  826. if (startIndex == -1) {
  827. return null;
  828. } else if (currCompilationResult.compilationUnit.getContents()[startIndex] == '/') {
  829. char[] comment = CharOperation.subarray(currCompilationResult.compilationUnit.getContents(), startIndex,
  830. astNode.sourceStart);
  831. while (comment.length > 2) {
  832. int star = CharOperation.indexOf('*', comment);
  833. if (star == -1) {
  834. return null;
  835. }
  836. // looking for '/**' and not '//' or '//*'
  837. if (star != 0 && (comment[star - 1] == '/') && (comment[star + 1] == '*')
  838. && (star - 2 < 0 || comment[star - 2] != '/')) {
  839. boolean completed = false;
  840. StringBuffer sb = new StringBuffer();
  841. for (int i = 0; i < comment.length && !completed; i++) {
  842. char curr = comment[i];
  843. if (curr == '/' && sb.length() > 2 && sb.charAt(sb.length() - 1) == '*') {
  844. completed = true; // found */
  845. }
  846. sb.append(comment[i]);
  847. }
  848. // The following will remove any non-javadoc comments
  849. // preceeding a javadoc comment in this block
  850. if (sb.toString().indexOf("/**") != 0) {
  851. return sb.toString().substring(sb.toString().indexOf("/**"));
  852. }
  853. return sb.toString();
  854. }
  855. comment = CharOperation.subarray(comment, star + 1, comment.length);
  856. }
  857. }
  858. return null;
  859. }
  860. /**
  861. *
  862. */
  863. protected String genSourceSignature(FieldDeclaration fieldDeclaration) {
  864. StringBuffer output = new StringBuffer();
  865. if (fieldDeclaration.type == null) { // This is an enum value
  866. output.append(fieldDeclaration.name); // the "," or ";" has to be
  867. // put on by whatever uses
  868. // the sourceSignature
  869. return output.toString();
  870. } else {
  871. FieldDeclaration.printModifiers(fieldDeclaration.modifiers, output);
  872. fieldDeclaration.type.print(0, output).append(' ').append(fieldDeclaration.name);
  873. }
  874. output.append(" = ");
  875. if (fieldDeclaration.initialization != null
  876. && (fieldDeclaration.initialization instanceof Literal
  877. || fieldDeclaration.initialization instanceof OperatorExpression || fieldDeclaration.initialization instanceof Reference)) {
  878. fieldDeclaration.initialization.printExpression(0, output);
  879. } else {
  880. output.append("null");
  881. }
  882. output.append(";\n");
  883. return output.toString();
  884. }
  885. // public boolean visit(ImportReference importRef, CompilationUnitScope
  886. // scope) {
  887. // ProgramElementNode peNode = new ProgramElementNode(
  888. // new String(importRef.toString()),
  889. // ProgramElementNode.Kind.,
  890. // makeLocation(importRef),
  891. // 0,
  892. // "",
  893. // new ArrayList());
  894. // ((IProgramElement)stack.peek()).addChild(0, peNode);
  895. // stack.push(peNode);
  896. // return true;
  897. // }
  898. // public void endVisit(ImportReference importRef,CompilationUnitScope
  899. // scope) {
  900. // stack.pop();
  901. // }
  902. public boolean visit(ConstructorDeclaration constructorDeclaration, ClassScope scope) {
  903. if ((constructorDeclaration.bits & ASTNode.IsDefaultConstructor) != 0) {
  904. stack.push(null); // a little weird but does the job
  905. return true;
  906. }
  907. StringBuffer argumentsSignature = new StringBuffer();
  908. argumentsSignature.append("(");
  909. if (constructorDeclaration.arguments != null) {
  910. for (int i = 0; i < constructorDeclaration.arguments.length; i++) {
  911. argumentsSignature.append(constructorDeclaration.arguments[i].type);
  912. if (i + 1 < constructorDeclaration.arguments.length) {
  913. argumentsSignature.append(",");
  914. }
  915. }
  916. }
  917. argumentsSignature.append(")");
  918. IProgramElement peNode = new ProgramElement(activeStructureModel, new String(constructorDeclaration.selector),
  919. IProgramElement.Kind.CONSTRUCTOR, makeLocation(constructorDeclaration), constructorDeclaration.modifiers, null,
  920. null);
  921. formatter.setParameters(constructorDeclaration, peNode);
  922. peNode.setModifiers(constructorDeclaration.modifiers);
  923. peNode.setSourceSignature(genSourceSignature(constructorDeclaration));
  924. peNode.setFormalComment(generateJavadocComment(constructorDeclaration));
  925. // Fix to enable us to anchor things from ctor nodes
  926. if (constructorDeclaration.binding != null) {
  927. String memberName = "";
  928. String memberBytecodeSignature = "";
  929. try {
  930. EclipseFactory factory = ((AjLookupEnvironment) constructorDeclaration.scope.environment()).factory;
  931. Member member = factory.makeResolvedMember(constructorDeclaration.binding);
  932. memberName = member.getName();
  933. memberBytecodeSignature = member.getSignature();
  934. } catch (BCException bce) { // bad type name
  935. memberName = "<undefined>";
  936. } catch (NullPointerException npe) {
  937. memberName = "<undefined>";
  938. }
  939. peNode.setBytecodeName(memberName);
  940. peNode.setBytecodeSignature(memberBytecodeSignature);
  941. }
  942. ((IProgramElement) stack.peek()).addChild(peNode);
  943. stack.push(peNode);
  944. return true;
  945. }
  946. public void endVisit(ConstructorDeclaration constructorDeclaration, ClassScope scope) {
  947. stack.pop();
  948. }
  949. private String genSourceSignature(ConstructorDeclaration constructorDeclaration) {
  950. StringBuffer output = new StringBuffer();
  951. ASTNode.printModifiers(constructorDeclaration.modifiers, output);
  952. // Append Type Parameters if any
  953. TypeParameter types[] = constructorDeclaration.typeParameters();
  954. if (types != null && types.length != 0) {
  955. output.append("<");
  956. for (int i = 0; i < types.length; i++) {
  957. if (i > 0) {
  958. output.append(", ");
  959. }
  960. types[i].printStatement(0, output);
  961. }
  962. output.append("> ");
  963. }
  964. output.append(constructorDeclaration.selector).append('(');
  965. if (constructorDeclaration.arguments != null) {
  966. for (int i = 0; i < constructorDeclaration.arguments.length; i++) {
  967. if (i > 0) {
  968. output.append(", "); //$NON-NLS-1$
  969. }
  970. constructorDeclaration.arguments[i].print(0, output);
  971. }
  972. }
  973. output.append(')');
  974. if (constructorDeclaration.thrownExceptions != null) {
  975. output.append(" throws "); //$NON-NLS-1$
  976. for (int i = 0; i < constructorDeclaration.thrownExceptions.length; i++) {
  977. if (i > 0) {
  978. output.append(", "); //$NON-NLS-1$
  979. }
  980. constructorDeclaration.thrownExceptions[i].print(0, output);
  981. }
  982. }
  983. return output.toString();
  984. }
  985. // public boolean visit(Clinit clinit, ClassScope scope) {
  986. // ProgramElementNode peNode = new ProgramElementNode(
  987. // "<clinit>",
  988. // ProgramElementNode.Kind.INITIALIZER,
  989. // makeLocation(clinit),
  990. // clinit.modifiers,
  991. // "",
  992. // new ArrayList());
  993. // ((IProgramElement)stack.peek()).addChild(peNode);
  994. // stack.push(peNode);
  995. // return false;
  996. // }
  997. // public void endVisit(Clinit clinit, ClassScope scope) {
  998. // stack.pop();
  999. // }
  1000. /**
  1001. * This method works-around an odd traverse implementation on Initializer
  1002. */
  1003. private Initializer inInitializer = null;
  1004. public boolean visit(Initializer initializer, MethodScope scope) {
  1005. if (initializer == inInitializer) {
  1006. return false;
  1007. }
  1008. inInitializer = initializer;
  1009. IProgramElement peNode = new ProgramElement(activeStructureModel, "...", IProgramElement.Kind.INITIALIZER,
  1010. makeLocation(initializer), initializer.modifiers, null, null);
  1011. // "",
  1012. // new ArrayList());
  1013. ((IProgramElement) stack.peek()).addChild(peNode);
  1014. stack.push(peNode);
  1015. initializer.block.traverse(this, scope);
  1016. stack.pop();
  1017. inInitializer = null;
  1018. return false;
  1019. }
  1020. // ??? handle non-existant files
  1021. protected ISourceLocation makeLocation(ASTNode node) {
  1022. String fileName = "";
  1023. if (filename != null) {
  1024. fileName = filename;
  1025. }
  1026. // AMC - different strategies based on node kind
  1027. int startLine = getStartLine(node);
  1028. int endLine = getEndLine(node);
  1029. SourceLocation loc = null;
  1030. if (startLine <= endLine) {
  1031. // found a valid end line for this node...
  1032. loc = new SourceLocation(new File(fileName), startLine, endLine);
  1033. loc.setOffset(node.sourceStart);
  1034. } else {
  1035. loc = new SourceLocation(new File(fileName), startLine);
  1036. loc.setOffset(node.sourceStart);
  1037. }
  1038. return loc;
  1039. }
  1040. // AMC - overloaded set of methods to get start and end lines for
  1041. // various ASTNode types. They have no common ancestor in the
  1042. // hierarchy!!
  1043. protected int getStartLine(ASTNode n) {
  1044. // if ( n instanceof AbstractVariableDeclaration ) return getStartLine(
  1045. // (AbstractVariableDeclaration)n);
  1046. // if ( n instanceof AbstractMethodDeclaration ) return getStartLine(
  1047. // (AbstractMethodDeclaration)n);
  1048. // if ( n instanceof TypeDeclaration ) return getStartLine(
  1049. // (TypeDeclaration)n);
  1050. return Util.getLineNumber(n.sourceStart, lineseps, 0, lineseps.length - 1);
  1051. // return ProblemHandler.searchLineNumber(lineseps,
  1052. // currCompilationResult.lineSeparatorPositions,
  1053. // n.sourceStart);
  1054. }
  1055. // AMC - overloaded set of methods to get start and end lines for
  1056. // various ASTNode types. They have no common ancestor in the
  1057. // hierarchy!!
  1058. protected int getEndLine(ASTNode n) {
  1059. if (n instanceof AbstractVariableDeclaration) {
  1060. return getEndLine((AbstractVariableDeclaration) n);
  1061. }
  1062. if (n instanceof AbstractMethodDeclaration) {
  1063. return getEndLine((AbstractMethodDeclaration) n);
  1064. }
  1065. if (n instanceof TypeDeclaration) {
  1066. return getEndLine((TypeDeclaration) n);
  1067. }
  1068. return Util.getLineNumber(n.sourceEnd, lineseps, 0, lineseps.length - 1);
  1069. // return ProblemHandler.searchLineNumber(lineseps,
  1070. // currCompilationResult.lineSeparatorPositions,
  1071. // n.sourceEnd);
  1072. }
  1073. // AMC - overloaded set of methods to get start and end lines for
  1074. // various ASTNode types. They have no common ancestor in the
  1075. // hierarchy!!
  1076. // private int getStartLine( AbstractVariableDeclaration avd ) {
  1077. // return ProblemHandler.searchLineNumber(
  1078. // currCompilationResult.lineSeparatorPositions,
  1079. // avd.declarationSourceStart);
  1080. // }
  1081. // AMC - overloaded set of methods to get start and end lines for
  1082. // various ASTNode types. They have no common ancestor in the
  1083. // hierarchy!!
  1084. private int getEndLine(AbstractVariableDeclaration avd) {
  1085. return Util.getLineNumber(avd.declarationSourceEnd, lineseps, 0, lineseps.length - 1);
  1086. }
  1087. // AMC - overloaded set of methods to get start and end lines for
  1088. // various ASTNode types. They have no common ancestor in the
  1089. // hierarchy!!
  1090. // private int getStartLine( AbstractMethodDeclaration amd ){
  1091. // return ProblemHandler.searchLineNumber(
  1092. // currCompilationResult.lineSeparatorPositions,
  1093. // amd.declarationSourceStart);
  1094. // }
  1095. // AMC - overloaded set of methods to get start and end lines for
  1096. // various ASTNode types. They have no common ancestor in the
  1097. // hierarchy!!
  1098. private int getEndLine(AbstractMethodDeclaration amd) {
  1099. return Util.getLineNumber(amd.declarationSourceEnd, lineseps, 0, lineseps.length - 1);
  1100. }
  1101. // AMC - overloaded set of methods to get start and end lines for
  1102. // various ASTNode types. They have no common ancestor in the
  1103. // hierarchy!!
  1104. // private int getStartLine( TypeDeclaration td ){
  1105. // return ProblemHandler.searchLineNumber(
  1106. // currCompilationResult.lineSeparatorPositions,
  1107. // td.declarationSourceStart);
  1108. // }
  1109. // AMC - overloaded set of methods to get start and end lines for
  1110. // various ASTNode types. They have no common ancestor in the
  1111. // hierarchy!!
  1112. private int getEndLine(TypeDeclaration td) {
  1113. return Util.getLineNumber(td.declarationSourceEnd, lineseps, 0, lineseps.length - 1);
  1114. }
  1115. }