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

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