Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

AsmHierarchyBuilder.java 45KB

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