Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

AsmHierarchyBuilder.java 26KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737
  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 Common Public License v1.0
  6. * which accompanies this distribution and is available at
  7. * http://www.eclipse.org/legal/cpl-v10.html
  8. *
  9. * Contributors:
  10. * PARC initial implementation
  11. * ******************************************************************/
  12. package org.aspectj.ajdt.internal.core.builder;
  13. import java.io.*;
  14. import java.util.*;
  15. import org.aspectj.ajdt.internal.compiler.ast.AspectDeclaration;
  16. import org.aspectj.ajdt.internal.compiler.ast.DeclareDeclaration;
  17. import org.aspectj.ajdt.internal.compiler.ast.InterTypeDeclaration;
  18. import org.aspectj.ajdt.internal.compiler.ast.InterTypeFieldDeclaration;
  19. import org.aspectj.ajdt.internal.compiler.ast.InterTypeMethodDeclaration;
  20. import org.aspectj.ajdt.internal.compiler.lookup.AjLookupEnvironment;
  21. import org.aspectj.ajdt.internal.compiler.lookup.EclipseFactory;
  22. import org.aspectj.asm.*;
  23. import org.aspectj.asm.internal.ProgramElement;
  24. import org.aspectj.bridge.*;
  25. import org.aspectj.util.LangUtil;
  26. import org.aspectj.weaver.Member;
  27. import org.aspectj.weaver.ResolvedMember;
  28. import org.eclipse.jdt.internal.compiler.*;
  29. import org.eclipse.jdt.internal.compiler.ast.*;
  30. import org.eclipse.jdt.internal.compiler.lookup.*;
  31. import org.eclipse.jdt.internal.compiler.problem.ProblemHandler;
  32. /**
  33. * At each iteration of <CODE>processCompilationUnit</CODE> the declarations for a
  34. * particular compilation unit are added to the hierarchy passed as a a parameter.
  35. *
  36. * Clients who extend this class need to ensure that they do not override any of the existing
  37. * behavior. If they do, the structure model will not be built properly and tools such as IDE
  38. * structure views and ajdoc will fail.
  39. *
  40. * @author Mik Kersten
  41. */
  42. public class AsmHierarchyBuilder extends ASTVisitor {
  43. // public static void build(
  44. // CompilationUnitDeclaration unit,
  45. // IHierarchy structureModel, AjBuildConfig buildConfig) {
  46. // LangUtil.throwIaxIfNull(unit, "unit");
  47. // new AsmHierarchyBuilder(unit., ).;
  48. // }
  49. protected AsmElementFormatter formatter = new AsmElementFormatter();
  50. /**
  51. * Reset for every compilation unit.
  52. */
  53. protected AjBuildConfig buildConfig;
  54. /**
  55. * Reset for every compilation unit.
  56. */
  57. protected Stack stack;
  58. /**
  59. * Reset for every compilation unit.
  60. */
  61. private CompilationResult currCompilationResult;
  62. /**
  63. *
  64. * @param cuDeclaration
  65. * @param buildConfig
  66. * @param structureModel hiearchy to add this unit's declarations to
  67. */
  68. public void buildStructureForCompilationUnit(CompilationUnitDeclaration cuDeclaration, IHierarchy structureModel, AjBuildConfig buildConfig) {
  69. currCompilationResult = cuDeclaration.compilationResult();
  70. LangUtil.throwIaxIfNull(currCompilationResult, "result");
  71. stack = new Stack();
  72. this.buildConfig = buildConfig;
  73. internalBuild(cuDeclaration, structureModel);
  74. // throw new RuntimeException("not implemented");
  75. }
  76. private void internalBuild(CompilationUnitDeclaration unit, IHierarchy structureModel) {
  77. LangUtil.throwIaxIfNull(structureModel, "structureModel");
  78. if (!currCompilationResult.equals(unit.compilationResult())) {
  79. throw new IllegalArgumentException("invalid unit: " + unit);
  80. }
  81. // ---- summary
  82. // add unit to package (or root if no package),
  83. // first removing any duplicate (XXX? removes children if 3 classes in same file?)
  84. // push the node on the stack
  85. // and traverse
  86. // -- create node to add
  87. final File file = new File(new String(unit.getFileName()));
  88. final IProgramElement cuNode;
  89. {
  90. // AMC - use the source start and end from the compilation unit decl
  91. int startLine = getStartLine(unit);
  92. int endLine = getEndLine(unit);
  93. ISourceLocation sourceLocation
  94. = new SourceLocation(file, startLine, endLine);
  95. cuNode = new ProgramElement(
  96. new String(file.getName()),
  97. IProgramElement.Kind.FILE_JAVA,
  98. sourceLocation,
  99. 0,
  100. "",
  101. new ArrayList());
  102. }
  103. cuNode.addChild(new ProgramElement(
  104. "import declarations",
  105. IProgramElement.Kind.IMPORT_REFERENCE,
  106. null,
  107. 0,
  108. "",
  109. new ArrayList()));
  110. final IProgramElement addToNode = genAddToNode(unit, structureModel);
  111. // -- remove duplicates before adding (XXX use them instead?)
  112. if (addToNode!=null && addToNode.getChildren()!=null) {
  113. for (ListIterator itt = addToNode.getChildren().listIterator(); itt.hasNext(); ) {
  114. IProgramElement child = (IProgramElement)itt.next();
  115. ISourceLocation childLoc = child.getSourceLocation();
  116. if (null == childLoc) {
  117. // XXX ok, packages have null source locations
  118. // signal others?
  119. } else if (childLoc.getSourceFile().equals(file)) {
  120. itt.remove();
  121. }
  122. }
  123. }
  124. // -- add and traverse
  125. addToNode.addChild(cuNode);
  126. stack.push(cuNode);
  127. unit.traverse(this, unit.scope);
  128. // -- update file map (XXX do this before traversal?)
  129. try {
  130. structureModel.addToFileMap(file.getCanonicalPath(), cuNode);
  131. } catch (IOException e) {
  132. System.err.println("IOException " + e.getMessage()
  133. + " creating path for " + file );
  134. // XXX signal IOException when canonicalizing file path
  135. }
  136. }
  137. /**
  138. * Get/create the node (package or root) to add to.
  139. */
  140. private IProgramElement genAddToNode(
  141. CompilationUnitDeclaration unit,
  142. IHierarchy structureModel) {
  143. final IProgramElement addToNode;
  144. {
  145. ImportReference currentPackage = unit.currentPackage;
  146. if (null == currentPackage) {
  147. addToNode = structureModel.getRoot();
  148. } else {
  149. String pkgName;
  150. {
  151. StringBuffer nameBuffer = new StringBuffer();
  152. final char[][] importName = currentPackage.getImportName();
  153. final int last = importName.length-1;
  154. for (int i = 0; i < importName.length; i++) {
  155. nameBuffer.append(new String(importName[i]));
  156. if (i < last) {
  157. nameBuffer.append('.');
  158. }
  159. }
  160. pkgName = nameBuffer.toString();
  161. }
  162. IProgramElement pkgNode = null;
  163. if (structureModel!=null && structureModel.getRoot()!=null && structureModel.getRoot().getChildren()!=null) {
  164. for (Iterator it = structureModel.getRoot().getChildren().iterator();
  165. it.hasNext(); ) {
  166. IProgramElement currNode = (IProgramElement)it.next();
  167. if (pkgName.equals(currNode.getName())) {
  168. pkgNode = currNode;
  169. break;
  170. }
  171. }
  172. }
  173. if (pkgNode == null) {
  174. // note packages themselves have no source location
  175. pkgNode = new ProgramElement(
  176. pkgName,
  177. IProgramElement.Kind.PACKAGE,
  178. new ArrayList()
  179. );
  180. structureModel.getRoot().addChild(pkgNode);
  181. }
  182. addToNode = pkgNode;
  183. }
  184. }
  185. return addToNode;
  186. }
  187. public boolean visit(TypeDeclaration typeDeclaration, CompilationUnitScope scope) {
  188. String name = new String(typeDeclaration.name);
  189. IProgramElement.Kind kind = IProgramElement.Kind.CLASS;
  190. if (typeDeclaration instanceof AspectDeclaration) kind = IProgramElement.Kind.ASPECT;
  191. else if (typeDeclaration.isInterface()) kind = IProgramElement.Kind.INTERFACE;
  192. IProgramElement peNode = new ProgramElement(
  193. name,
  194. kind,
  195. makeLocation(typeDeclaration),
  196. typeDeclaration.modifiers,
  197. "",
  198. new ArrayList());
  199. peNode.setSourceSignature(genSourceSignature(typeDeclaration));
  200. peNode.setFormalComment(generateJavadocComment(typeDeclaration));
  201. ((IProgramElement)stack.peek()).addChild(peNode);
  202. stack.push(peNode);
  203. return true;
  204. }
  205. public void endVisit(TypeDeclaration typeDeclaration, CompilationUnitScope scope) {
  206. stack.pop();
  207. }
  208. // ??? share impl with visit(TypeDeclaration, ..) ?
  209. public boolean visit(TypeDeclaration memberTypeDeclaration, ClassScope scope) {
  210. String name = new String(memberTypeDeclaration.name);
  211. //System.err.println("member type with name: " + name);
  212. IProgramElement.Kind kind = IProgramElement.Kind.CLASS;
  213. if (memberTypeDeclaration instanceof AspectDeclaration) kind = IProgramElement.Kind.ASPECT;
  214. else if (memberTypeDeclaration.isInterface()) kind = IProgramElement.Kind.INTERFACE;
  215. IProgramElement peNode = new ProgramElement(
  216. name,
  217. kind,
  218. makeLocation(memberTypeDeclaration),
  219. memberTypeDeclaration.modifiers,
  220. "",
  221. new ArrayList());
  222. peNode.setSourceSignature(genSourceSignature(memberTypeDeclaration));
  223. peNode.setFormalComment(generateJavadocComment(memberTypeDeclaration));
  224. ((IProgramElement)stack.peek()).addChild(peNode);
  225. stack.push(peNode);
  226. return true;
  227. }
  228. public void endVisit(TypeDeclaration memberTypeDeclaration, ClassScope scope) {
  229. stack.pop();
  230. }
  231. public boolean visit(TypeDeclaration memberTypeDeclaration, BlockScope scope) {
  232. // String name = new String(memberTypeDeclaration.name);
  233. String fullName = "<undefined>";
  234. if (memberTypeDeclaration.binding != null
  235. && memberTypeDeclaration.binding.constantPoolName() != null) {
  236. fullName = new String(memberTypeDeclaration.binding.constantPoolName());
  237. }
  238. int dollar = fullName.indexOf('$');
  239. fullName = fullName.substring(dollar+1);
  240. IProgramElement.Kind kind = IProgramElement.Kind.CLASS;
  241. if (memberTypeDeclaration.isInterface()) kind = IProgramElement.Kind.INTERFACE;
  242. IProgramElement peNode = new ProgramElement(
  243. fullName,
  244. kind,
  245. makeLocation(memberTypeDeclaration),
  246. memberTypeDeclaration.modifiers,
  247. "",
  248. new ArrayList());
  249. peNode.setSourceSignature(genSourceSignature(memberTypeDeclaration));
  250. peNode.setFormalComment(generateJavadocComment(memberTypeDeclaration));
  251. //??? we add this to the compilation unit
  252. findEnclosingClass(stack).addChild(peNode);
  253. stack.push(peNode);
  254. return true;
  255. }
  256. public void endVisit(TypeDeclaration memberTypeDeclaration, BlockScope scope) {
  257. stack.pop();
  258. }
  259. private String genSourceSignature(TypeDeclaration typeDeclaration) {
  260. StringBuffer output = new StringBuffer();
  261. typeDeclaration.printHeader(0, output);
  262. return output.toString();
  263. }
  264. private IProgramElement findEnclosingClass(Stack stack) {
  265. for (int i = stack.size()-1; i >= 0; i--) {
  266. IProgramElement pe = (IProgramElement)stack.get(i);
  267. if (pe.getKind() == IProgramElement.Kind.CLASS) {
  268. return pe;
  269. }
  270. }
  271. return (IProgramElement)stack.peek();
  272. }
  273. public boolean visit(MethodDeclaration methodDeclaration, ClassScope scope) {
  274. IProgramElement peNode = null;
  275. // For intertype decls, use the modifiers from the original signature, not the generated method
  276. if (methodDeclaration instanceof InterTypeDeclaration) {
  277. InterTypeDeclaration itd = (InterTypeDeclaration) methodDeclaration;
  278. ResolvedMember sig = itd.getSignature();
  279. peNode = new ProgramElement(
  280. "",
  281. IProgramElement.Kind.ERROR,
  282. makeLocation(methodDeclaration),
  283. (sig!=null?sig.getModifiers():0),
  284. "",
  285. new ArrayList());
  286. } else {
  287. peNode = new ProgramElement(
  288. "",
  289. IProgramElement.Kind.ERROR,
  290. makeLocation(methodDeclaration),
  291. methodDeclaration.modifiers,
  292. "",
  293. new ArrayList());
  294. }
  295. formatter.genLabelAndKind(methodDeclaration, peNode);
  296. genBytecodeInfo(methodDeclaration, peNode);
  297. if (methodDeclaration.returnType!=null) {
  298. peNode.setCorrespondingType(methodDeclaration.returnType.toString());
  299. } else {
  300. peNode.setCorrespondingType(null);
  301. }
  302. peNode.setSourceSignature(genSourceSignature(methodDeclaration));
  303. peNode.setFormalComment(generateJavadocComment(methodDeclaration));
  304. // TODO: add return type test
  305. if (peNode.getKind().equals(IProgramElement.Kind.METHOD)) {
  306. if (peNode.toLabelString().equals("main(String[])")
  307. && peNode.getModifiers().contains(IProgramElement.Modifiers.STATIC)
  308. && peNode.getAccessibility().equals(IProgramElement.Accessibility.PUBLIC)) {
  309. ((IProgramElement)stack.peek()).setRunnable(true);
  310. }
  311. }
  312. stack.push(peNode);
  313. return true;
  314. }
  315. private String genSourceSignature(MethodDeclaration methodDeclaration) {
  316. StringBuffer output = new StringBuffer();
  317. ASTNode.printModifiers(methodDeclaration.modifiers, output);
  318. methodDeclaration.printReturnType(0, output).append(methodDeclaration.selector).append('(');
  319. if (methodDeclaration.arguments != null) {
  320. for (int i = 0; i < methodDeclaration.arguments.length; i++) {
  321. if (i > 0) output.append(", "); //$NON-NLS-1$
  322. methodDeclaration.arguments[i].print(0, output);
  323. }
  324. }
  325. output.append(')');
  326. if (methodDeclaration.thrownExceptions != null) {
  327. output.append(" throws "); //$NON-NLS-1$
  328. for (int i = 0; i < methodDeclaration.thrownExceptions.length; i++) {
  329. if (i > 0) output.append(", "); //$NON-NLS-1$
  330. methodDeclaration.thrownExceptions[i].print(0, output);
  331. }
  332. }
  333. return output.toString();
  334. }
  335. private void genBytecodeInfo(MethodDeclaration methodDeclaration, IProgramElement peNode) {
  336. if (methodDeclaration.binding != null) {
  337. String memberName = "";
  338. String memberBytecodeSignature = "";
  339. try {
  340. Member member = EclipseFactory.makeResolvedMember(methodDeclaration.binding);
  341. memberName = member.getName();
  342. memberBytecodeSignature = member.getSignature();
  343. } catch (NullPointerException npe) {
  344. memberName = "<undefined>";
  345. }
  346. peNode.setBytecodeName(memberName);
  347. peNode.setBytecodeSignature(memberBytecodeSignature);
  348. }
  349. ((IProgramElement)stack.peek()).addChild(peNode);
  350. }
  351. public void endVisit(MethodDeclaration methodDeclaration, ClassScope scope) {
  352. stack.pop();
  353. }
  354. public boolean visit(ImportReference importRef, CompilationUnitScope scope) {
  355. int dotIndex = importRef.toString().lastIndexOf('.');
  356. String currPackageImport = "";
  357. if (dotIndex != -1) {
  358. currPackageImport = importRef.toString().substring(0, dotIndex);
  359. }
  360. if (!((ProgramElement)stack.peek()).getPackageName().equals(currPackageImport)) {
  361. IProgramElement peNode = new ProgramElement(
  362. new String(importRef.toString()),
  363. IProgramElement.Kind.IMPORT_REFERENCE,
  364. makeLocation(importRef),
  365. 0,
  366. "",
  367. new ArrayList());
  368. ProgramElement imports = (ProgramElement)((ProgramElement)stack.peek()).getChildren().get(0);
  369. imports.addChild(0, peNode);
  370. stack.push(peNode);
  371. }
  372. return true;
  373. }
  374. public void endVisit(ImportReference importRef, CompilationUnitScope scope) {
  375. int dotIndex = importRef.toString().lastIndexOf('.');
  376. String currPackageImport = "";
  377. if (dotIndex != -1) {
  378. currPackageImport = importRef.toString().substring(0, dotIndex);
  379. }
  380. if (!((ProgramElement)stack.peek()).getPackageName().equals(currPackageImport)) {
  381. stack.pop();
  382. }
  383. }
  384. public boolean visit(FieldDeclaration fieldDeclaration, MethodScope scope) {
  385. IProgramElement peNode = new ProgramElement(
  386. new String(fieldDeclaration.name),
  387. IProgramElement.Kind.FIELD,
  388. makeLocation(fieldDeclaration),
  389. fieldDeclaration.modifiers,
  390. "",
  391. new ArrayList());
  392. peNode.setCorrespondingType(fieldDeclaration.type.toString());
  393. peNode.setSourceSignature(genSourceSignature(fieldDeclaration));
  394. peNode.setFormalComment(generateJavadocComment(fieldDeclaration));
  395. ((IProgramElement)stack.peek()).addChild(peNode);
  396. stack.push(peNode);
  397. return true;
  398. }
  399. public void endVisit(FieldDeclaration fieldDeclaration, MethodScope scope) {
  400. stack.pop();
  401. }
  402. /**
  403. * Checks if comments should be added to the model before generating.
  404. */
  405. private String generateJavadocComment(ASTNode astNode) {
  406. if (buildConfig != null && !buildConfig.isGenerateJavadocsInModelMode()) return null;
  407. StringBuffer sb = new StringBuffer(); // !!! specify length?
  408. boolean completed = false;
  409. int startIndex = -1;
  410. if (astNode instanceof MethodDeclaration) {
  411. startIndex = ((MethodDeclaration)astNode).declarationSourceStart;
  412. } else if (astNode instanceof FieldDeclaration) {
  413. startIndex = ((FieldDeclaration)astNode).declarationSourceStart;
  414. } else if (astNode instanceof TypeDeclaration) {
  415. startIndex = ((TypeDeclaration)astNode).declarationSourceStart;
  416. }
  417. if (startIndex == -1) {
  418. return null;
  419. } else if (currCompilationResult.compilationUnit.getContents()[startIndex] == '/' // look for /**
  420. && currCompilationResult.compilationUnit.getContents()[startIndex+1] == '*'
  421. && currCompilationResult.compilationUnit.getContents()[startIndex+2] == '*') {
  422. for (int i = startIndex; i < astNode.sourceStart && !completed; i++) {
  423. char curr = currCompilationResult.compilationUnit.getContents()[i];
  424. if (curr == '/' && sb.length() > 2 && sb.charAt(sb.length()-1) == '*') completed = true; // found */
  425. sb.append(currCompilationResult.compilationUnit.getContents()[i]);
  426. }
  427. // System.err.println(">> " + sb.toString());
  428. return sb.toString();
  429. } else {
  430. return null;
  431. }
  432. }
  433. /**
  434. * Doesn't print qualified allocation expressions.
  435. */
  436. private String genSourceSignature(FieldDeclaration fieldDeclaration) {
  437. StringBuffer output = new StringBuffer();
  438. FieldDeclaration.printModifiers(fieldDeclaration.modifiers, output);
  439. fieldDeclaration.type.print(0, output).append(' ').append(fieldDeclaration.name);
  440. if (fieldDeclaration.initialization != null
  441. && !(fieldDeclaration.initialization instanceof QualifiedAllocationExpression)) {
  442. output.append(" = "); //$NON-NLS-1$
  443. if (fieldDeclaration.initialization instanceof ExtendedStringLiteral) {
  444. output.append("\"<extended string literal>\"");
  445. } else {
  446. fieldDeclaration.initialization.printExpression(0, output);
  447. }
  448. }
  449. output.append(';');
  450. return output.toString();
  451. }
  452. // public boolean visit(ImportReference importRef, CompilationUnitScope scope) {
  453. // ProgramElementNode peNode = new ProgramElementNode(
  454. // new String(importRef.toString()),
  455. // ProgramElementNode.Kind.,
  456. // makeLocation(importRef),
  457. // 0,
  458. // "",
  459. // new ArrayList());
  460. // ((IProgramElement)stack.peek()).addChild(0, peNode);
  461. // stack.push(peNode);
  462. // return true;
  463. // }
  464. // public void endVisit(ImportReference importRef,CompilationUnitScope scope) {
  465. // stack.pop();
  466. // }
  467. public boolean visit(ConstructorDeclaration constructorDeclaration, ClassScope scope) {
  468. if (constructorDeclaration.isDefaultConstructor) {
  469. stack.push(null); // a little wierd but does the job
  470. return true;
  471. }
  472. StringBuffer argumentsSignature = new StringBuffer();
  473. argumentsSignature.append("(");
  474. if (constructorDeclaration.arguments!=null) {
  475. for (int i = 0;i<constructorDeclaration.arguments.length;i++) {
  476. argumentsSignature.append(constructorDeclaration.arguments[i]);
  477. if (i+1<constructorDeclaration.arguments.length) argumentsSignature.append(",");
  478. }
  479. }
  480. argumentsSignature.append(")");
  481. IProgramElement peNode = new ProgramElement(
  482. new String(constructorDeclaration.selector)+argumentsSignature,
  483. IProgramElement.Kind.CONSTRUCTOR,
  484. makeLocation(constructorDeclaration),
  485. constructorDeclaration.modifiers,
  486. "",
  487. new ArrayList());
  488. peNode.setModifiers(constructorDeclaration.modifiers);
  489. peNode.setSourceSignature(genSourceSignature(constructorDeclaration));
  490. // Fix to enable us to anchor things from ctor nodes
  491. if (constructorDeclaration.binding != null) {
  492. String memberName = "";
  493. String memberBytecodeSignature = "";
  494. try {
  495. Member member = EclipseFactory.makeResolvedMember(constructorDeclaration.binding);
  496. memberName = member.getName();
  497. memberBytecodeSignature = member.getSignature();
  498. } catch (NullPointerException npe) {
  499. memberName = "<undefined>";
  500. }
  501. peNode.setBytecodeName(memberName);
  502. peNode.setBytecodeSignature(memberBytecodeSignature);
  503. }
  504. ((IProgramElement)stack.peek()).addChild(peNode);
  505. stack.push(peNode);
  506. return true;
  507. }
  508. public void endVisit(ConstructorDeclaration constructorDeclaration, ClassScope scope) {
  509. stack.pop();
  510. }
  511. private String genSourceSignature(ConstructorDeclaration constructorDeclaration) {
  512. StringBuffer output = new StringBuffer();
  513. ASTNode.printModifiers(constructorDeclaration.modifiers, output);
  514. output.append(constructorDeclaration.selector).append('(');
  515. if (constructorDeclaration.arguments != null) {
  516. for (int i = 0; i < constructorDeclaration.arguments.length; i++) {
  517. if (i > 0) output.append(", "); //$NON-NLS-1$
  518. constructorDeclaration.arguments[i].print(0, output);
  519. }
  520. }
  521. output.append(')');
  522. if (constructorDeclaration.thrownExceptions != null) {
  523. output.append(" throws "); //$NON-NLS-1$
  524. for (int i = 0; i < constructorDeclaration.thrownExceptions.length; i++) {
  525. if (i > 0) output.append(", "); //$NON-NLS-1$
  526. constructorDeclaration.thrownExceptions[i].print(0, output);
  527. }
  528. }
  529. return output.toString();
  530. }
  531. // public boolean visit(Clinit clinit, ClassScope scope) {
  532. // ProgramElementNode peNode = new ProgramElementNode(
  533. // "<clinit>",
  534. // ProgramElementNode.Kind.INITIALIZER,
  535. // makeLocation(clinit),
  536. // clinit.modifiers,
  537. // "",
  538. // new ArrayList());
  539. // ((IProgramElement)stack.peek()).addChild(peNode);
  540. // stack.push(peNode);
  541. // return false;
  542. // }
  543. // public void endVisit(Clinit clinit, ClassScope scope) {
  544. // stack.pop();
  545. // }
  546. /** This method works-around an odd traverse implementation on Initializer
  547. */
  548. private Initializer inInitializer = null;
  549. public boolean visit(Initializer initializer, MethodScope scope) {
  550. if (initializer == inInitializer) return false;
  551. inInitializer = initializer;
  552. IProgramElement peNode = new ProgramElement(
  553. "...",
  554. IProgramElement.Kind.INITIALIZER,
  555. makeLocation(initializer),
  556. initializer.modifiers,
  557. "",
  558. new ArrayList());
  559. ((IProgramElement)stack.peek()).addChild(peNode);
  560. stack.push(peNode);
  561. initializer.block.traverse(this, scope);
  562. stack.pop();
  563. return false;
  564. }
  565. // ??? handle non-existant files
  566. private ISourceLocation makeLocation(ASTNode node) {
  567. String fileName = "";
  568. if (currCompilationResult.getFileName() != null) {
  569. fileName = new String(currCompilationResult.getFileName());
  570. }
  571. // AMC - different strategies based on node kind
  572. int startLine = getStartLine(node);
  573. int endLine = getEndLine(node);
  574. ISourceLocation loc = null;
  575. if ( startLine <= endLine ) {
  576. // found a valid end line for this node...
  577. loc = new SourceLocation(new File(fileName), startLine, endLine);
  578. } else {
  579. loc = new SourceLocation(new File(fileName), startLine);
  580. }
  581. return loc;
  582. }
  583. // AMC - overloaded set of methods to get start and end lines for
  584. // various ASTNode types. They have no common ancestor in the
  585. // hierarchy!!
  586. private int getStartLine( ASTNode n){
  587. // if ( n instanceof AbstractVariableDeclaration ) return getStartLine( (AbstractVariableDeclaration)n);
  588. // if ( n instanceof AbstractMethodDeclaration ) return getStartLine( (AbstractMethodDeclaration)n);
  589. // if ( n instanceof TypeDeclaration ) return getStartLine( (TypeDeclaration)n);
  590. return ProblemHandler.searchLineNumber(
  591. currCompilationResult.lineSeparatorPositions,
  592. n.sourceStart);
  593. }
  594. // AMC - overloaded set of methods to get start and end lines for
  595. // various ASTNode types. They have no common ancestor in the
  596. // hierarchy!!
  597. private int getEndLine( ASTNode n){
  598. if ( n instanceof AbstractVariableDeclaration ) return getEndLine( (AbstractVariableDeclaration)n);
  599. if ( n instanceof AbstractMethodDeclaration ) return getEndLine( (AbstractMethodDeclaration)n);
  600. if ( n instanceof TypeDeclaration ) return getEndLine( (TypeDeclaration)n);
  601. return ProblemHandler.searchLineNumber(
  602. currCompilationResult.lineSeparatorPositions,
  603. n.sourceEnd);
  604. }
  605. // AMC - overloaded set of methods to get start and end lines for
  606. // various ASTNode types. They have no common ancestor in the
  607. // hierarchy!!
  608. // private int getStartLine( AbstractVariableDeclaration avd ) {
  609. // return ProblemHandler.searchLineNumber(
  610. // currCompilationResult.lineSeparatorPositions,
  611. // avd.declarationSourceStart);
  612. // }
  613. // AMC - overloaded set of methods to get start and end lines for
  614. // various ASTNode types. They have no common ancestor in the
  615. // hierarchy!!
  616. private int getEndLine( AbstractVariableDeclaration avd ){
  617. return ProblemHandler.searchLineNumber(
  618. currCompilationResult.lineSeparatorPositions,
  619. avd.declarationSourceEnd);
  620. }
  621. // AMC - overloaded set of methods to get start and end lines for
  622. // various ASTNode types. They have no common ancestor in the
  623. // hierarchy!!
  624. // private int getStartLine( AbstractMethodDeclaration amd ){
  625. // return ProblemHandler.searchLineNumber(
  626. // currCompilationResult.lineSeparatorPositions,
  627. // amd.declarationSourceStart);
  628. // }
  629. // AMC - overloaded set of methods to get start and end lines for
  630. // various ASTNode types. They have no common ancestor in the
  631. // hierarchy!!
  632. private int getEndLine( AbstractMethodDeclaration amd) {
  633. return ProblemHandler.searchLineNumber(
  634. currCompilationResult.lineSeparatorPositions,
  635. amd.declarationSourceEnd);
  636. }
  637. // AMC - overloaded set of methods to get start and end lines for
  638. // various ASTNode types. They have no common ancestor in the
  639. // hierarchy!!
  640. // private int getStartLine( TypeDeclaration td ){
  641. // return ProblemHandler.searchLineNumber(
  642. // currCompilationResult.lineSeparatorPositions,
  643. // td.declarationSourceStart);
  644. // }
  645. // AMC - overloaded set of methods to get start and end lines for
  646. // various ASTNode types. They have no common ancestor in the
  647. // hierarchy!!
  648. private int getEndLine( TypeDeclaration td){
  649. return ProblemHandler.searchLineNumber(
  650. currCompilationResult.lineSeparatorPositions,
  651. td.declarationSourceEnd);
  652. }
  653. }