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.

ClassWriter.java 19KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554
  1. /* -*- Mode: JDE; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  2. *
  3. * This file is part of the debugger and core tools for the AspectJ(tm)
  4. * programming language; see http://aspectj.org
  5. *
  6. * The contents of this file are subject to the Mozilla Public License
  7. * Version 1.1 (the "License"); you may not use this file except in
  8. * compliance with the License. You may obtain a copy of the License at
  9. * either http://www.mozilla.org/MPL/ or http://aspectj.org/MPL/.
  10. *
  11. * Software distributed under the License is distributed on an "AS IS" basis,
  12. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  13. * for the specific language governing rights and limitations under the
  14. * License.
  15. *
  16. * The Original Code is AspectJ.
  17. *
  18. * The Initial Developer of the Original Code is Xerox Corporation. Portions
  19. * created by Xerox Corporation are Copyright (C) 1999-2002 Xerox Corporation.
  20. * All Rights Reserved.
  21. */
  22. package org.aspectj.tools.doclets.standard;
  23. import org.aspectj.ajdoc.AdviceDoc;
  24. import org.aspectj.ajdoc.AspectDoc;
  25. import org.aspectj.ajdoc.IntroducedDoc;
  26. import org.aspectj.ajdoc.IntroducedSuperDoc;
  27. import org.aspectj.ajdoc.IntroductionDoc;
  28. import org.aspectj.ajdoc.OfClauseDoc;
  29. import org.aspectj.ajdoc.OfEachObjectDoc;
  30. import com.sun.javadoc.ClassDoc;
  31. import com.sun.javadoc.ExecutableMemberDoc;
  32. import com.sun.javadoc.MemberDoc;
  33. import com.sun.tools.doclets.ClassTree;
  34. import com.sun.tools.doclets.DirectoryManager;
  35. import com.sun.tools.doclets.DocletAbortException;
  36. import java.io.IOException;
  37. import java.util.ArrayList;
  38. import java.util.Collection;
  39. import java.util.Iterator;
  40. import java.util.List;
  41. import java.util.Set;
  42. import java.util.TreeSet;
  43. public class ClassWriter extends com.sun.tools.doclets.standard.ClassWriter {
  44. /**
  45. * The MethodSubWriter that prints out the methods
  46. * of <code>classdoc</code>.
  47. */
  48. protected MethodSubWriter ourMethodSubWriter;
  49. /**
  50. * The ConstructorSubWriter that prints out the constructors
  51. * of <code>classdoc</code>.
  52. */
  53. protected ConstructorSubWriter ourConstrSubWriter;
  54. /**
  55. * The FieldSubWriter that prints out the fields
  56. * of <code>classdoc</code>.
  57. */
  58. protected FieldSubWriter ourFieldSubWriter;
  59. /**
  60. * The ClassSubWriter that prints out the classs
  61. * of <code>classdoc</code>.
  62. */
  63. protected ClassSubWriter ourInnerSubWriter;
  64. /**
  65. * The PointcutSubWriter that prints out the pointcuts
  66. * of <code>classdoc</code>.
  67. */
  68. protected PointcutSubWriter pointcutSubWriter = null;
  69. /**
  70. * The SuperIntroductionSubWriter that prints out the superintroductions
  71. * of <code>classdoc</code>.
  72. */
  73. protected SuperIntroductionSubWriter superIntroductionSubWriter = null;
  74. /**
  75. * The FieldIntroductionSubWriter that prints out the fieldintroductions
  76. * of <code>classdoc</code>.
  77. */
  78. protected FieldIntroductionSubWriter fieldIntroductionSubWriter = null;
  79. /**
  80. * The ConstructorIntroductionSubWriter that prints out the constructorintroductions
  81. * of <code>classdoc</code>.
  82. */
  83. protected ConstructorIntroductionSubWriter constrIntroductionSubWriter = null;
  84. /**
  85. * The MethodIntroductionSubWriter that prints out the methodintroductions
  86. * of <code>classdoc</code>.
  87. */
  88. protected MethodIntroductionSubWriter methodIntroductionSubWriter = null;
  89. /**
  90. * The AdviceSubWriter that prints out the advices
  91. * of <code>classdoc</code>.
  92. */
  93. protected AdviceSubWriter adviceSubWriter = null;
  94. /**
  95. * Construct a ClassWriter from the passed in arguments. This
  96. * will instantiate the subwriters to be used.
  97. *
  98. * @param path the path directory of the html file to generate.
  99. * @param filename the html file to generate.
  100. * @param classdoc the ClassDoc for which this file will
  101. * be generated.
  102. * @param prev the ClassDoc preceding <code>classdoc</code>
  103. * in order of generation.
  104. * @param next the ClassDoc following <code>classdoc</code>
  105. * in order of generation.
  106. * @param classtree the ClassTree to use.
  107. * @param nopackage whether this <code>classdoc</code>'s package
  108. * is specified to be documented.
  109. */
  110. public ClassWriter(String path,
  111. String filename,
  112. ClassDoc classdoc,
  113. ClassDoc prev,
  114. ClassDoc next,
  115. ClassTree classtree,
  116. boolean nopackage)
  117. throws IOException, DocletAbortException {
  118. super(path, filename, classdoc, prev,
  119. next, classtree, nopackage);
  120. // Construct the subwriters just for ClassDocs
  121. // We want our superclass to delegate to our subwriters delegate,
  122. // but we want to call our subwriters. So we set our superclasses
  123. // subwriters to our subwriters delegates.
  124. ourMethodSubWriter = new MethodSubWriter(this, classdoc);
  125. methodSubWriter = (com.sun.tools.doclets.standard.MethodSubWriter)
  126. ourMethodSubWriter.del();
  127. constrSubWriter = (com.sun.tools.doclets.standard.ConstructorSubWriter)
  128. (ourConstrSubWriter = new ConstructorSubWriter(this, classdoc)).del();
  129. fieldSubWriter = (com.sun.tools.doclets.standard.FieldSubWriter)
  130. (ourFieldSubWriter = new FieldSubWriter(this, classdoc)).del();
  131. innerSubWriter = (com.sun.tools.doclets.standard.ClassSubWriter)
  132. (ourInnerSubWriter = new ClassSubWriter(this, classdoc)).del();
  133. if (classdoc instanceof org.aspectj.ajdoc.ClassDoc) {
  134. pointcutSubWriter =
  135. new PointcutSubWriter(this, (org.aspectj.ajdoc.ClassDoc)classdoc);
  136. }
  137. // If we've been passed an AspectDoc, create the AspectJ-specfic
  138. // subwriters
  139. if (classdoc instanceof AspectDoc) {
  140. AspectDoc ad = (AspectDoc)classdoc;
  141. superIntroductionSubWriter = new SuperIntroductionSubWriter(this, ad);
  142. fieldIntroductionSubWriter = new FieldIntroductionSubWriter(this, ad);
  143. constrIntroductionSubWriter = new ConstructorIntroductionSubWriter(this, ad);
  144. methodIntroductionSubWriter = new MethodIntroductionSubWriter(this, ad);
  145. adviceSubWriter = new AdviceSubWriter(this, ad);
  146. }
  147. }
  148. public static void generate(ClassDoc classdoc,
  149. ClassDoc prev,
  150. ClassDoc next,
  151. ClassTree classtree,
  152. boolean nopackage)
  153. throws DocletAbortException {
  154. ClassWriter cw = null;
  155. String path = DirectoryManager.getDirectoryPath
  156. (classdoc.containingPackage());
  157. String filename = classdoc.name() + ".html";
  158. try {
  159. (cw = new ClassWriter(path, filename, classdoc,
  160. prev, next, classtree, nopackage)).
  161. generateClassFile();
  162. } catch (IOException e) {
  163. Standard.configuration().standardmessage.
  164. error("doclet.exception_encountered", e+"", filename);
  165. throw new DocletAbortException();
  166. } finally {
  167. if (cw != null) cw.close();
  168. }
  169. }
  170. /**
  171. * Prints the header of the class -- which is one
  172. * of <code>class</code>, <code>interface</code> or
  173. * <code>aspect</code> with the name <code>title</code>.
  174. *
  175. * @param title the name of the class.
  176. */
  177. public void printHeader(String title) {
  178. int ispace = title.indexOf(' ');
  179. if (ispace != -1) {
  180. title = Statics.type(classdoc) + title.substring(ispace);
  181. }
  182. super.printHeader(title);
  183. }
  184. /*
  185. * This is set up to intercept calls to print out
  186. * the correct type of classdoc before we automatically
  187. * print 'class' or 'interface'.
  188. */
  189. private boolean h2warn = false;
  190. /**
  191. * If we've started to print a h2 heading, we're
  192. * printing the name of the class so get ready to
  193. * to intercept the call.
  194. */
  195. public void h2() {
  196. h2warn = true;
  197. super.h2();
  198. }
  199. /**
  200. * After printing the class declaration with the h2 heading
  201. * turn off the h2 warning.
  202. */
  203. public void h2End() {
  204. h2warn = false;
  205. super.h2End();
  206. }
  207. /**
  208. * This is where we intercept the call to print so
  209. * we can print the correct type.
  210. */
  211. public void print(String str) {
  212. if (h2warn) {
  213. int ispace = str.indexOf(' ');
  214. if (ispace != -1 && str.charAt(0) == 'C') {
  215. str = Statics.type(classdoc) + str.substring(ispace);
  216. }
  217. }
  218. super.print(str);
  219. }
  220. /**
  221. * Print the members summary for our AspectJ subwriters.
  222. */
  223. protected void printAspectJSummary() {
  224. printMembersSummary(superIntroductionSubWriter);
  225. printMembersSummary(fieldIntroductionSubWriter);
  226. printMembersSummary(constrIntroductionSubWriter);
  227. printMembersSummary(methodIntroductionSubWriter);
  228. printMembersSummary(pointcutSubWriter);
  229. printMembersSummary(adviceSubWriter);
  230. }
  231. /**
  232. * Formats the output correctly for a member summary.
  233. *
  234. * @param mw the AbstractSubWriter to use.
  235. */
  236. protected final void printMembersSummary(AbstractSubWriter mw) {
  237. if (mw != null) {
  238. println();
  239. println("<!-- === " + getText(mw.navKey()) + " SUMMARY === -->");
  240. println();
  241. mw.printMembersSummary();
  242. }
  243. }
  244. /**
  245. * Print the members detail for our AspectJ subwriters.
  246. */
  247. protected void printAspectJDetail() {
  248. printMembersDetail(superIntroductionSubWriter);
  249. printMembersDetail(fieldIntroductionSubWriter);
  250. printMembersDetail(constrIntroductionSubWriter);
  251. printMembersDetail(methodIntroductionSubWriter);
  252. printMembersDetail(pointcutSubWriter);
  253. printMembersDetail(adviceSubWriter);
  254. }
  255. /**
  256. * Formats the output correctly for a member detail.
  257. *
  258. * @param mw the AbstractSubWriter to use.
  259. */
  260. protected final void printMembersDetail(AbstractSubWriter mw) {
  261. if (mw != null) {
  262. println("<!-- ===" + getText(mw.navKey()) + " DETAIL === -->");
  263. println();
  264. mw.printMembers();
  265. println();
  266. }
  267. }
  268. //TODO: Just need to make sure 'aspect; shows up and
  269. //TODO not 'class'
  270. protected void printClassDescription() {
  271. boolean isInterface = classdoc.isInterface();
  272. boolean isAspect = classdoc instanceof AspectDoc;
  273. dl();
  274. dt();
  275. print(classdoc.modifiers() + " ");
  276. if (!isInterface) {
  277. print(isAspect ? "aspect " : "class ");
  278. }
  279. bold(classdoc.name());
  280. if (!isInterface) {
  281. ClassDoc superclass = classdoc.superclass();
  282. if (superclass != null) {
  283. dt();
  284. print("extends ");
  285. printClassLink(superclass);
  286. printIntroducedSuper(superclass);
  287. }
  288. }
  289. ClassDoc[] implIntfacs = classdoc.interfaces();
  290. if (implIntfacs != null && implIntfacs.length > 0) {
  291. dt();
  292. print(isInterface? "extends " : "implements ");
  293. for (int i = 0; i < implIntfacs.length; i++) {
  294. if (i > 0) print(", ");
  295. printClassLink(implIntfacs[i]);
  296. printIntroducedSuper(implIntfacs[i]);
  297. }
  298. }
  299. if (isAspect) {
  300. AspectDoc ad = (AspectDoc)classdoc;
  301. OfClauseDoc ofClause = ad.ofClause();
  302. if (ofClause != null) {
  303. dt();
  304. if (ofClause.kind() == OfClauseDoc.Kind.EACH_CFLOW) {
  305. print("percflow(..)");
  306. } else if (ofClause.kind() == OfClauseDoc.Kind.EACH_JVM) {
  307. print("issingleton()");
  308. } else if (ofClause.kind() == OfClauseDoc.Kind.EACH_OBJECT) {
  309. print("pertarget(");
  310. printClassLinks(((OfEachObjectDoc)ofClause).instances());
  311. print(")");
  312. }
  313. }
  314. AspectDoc[] dominatees = ad.dominatees();
  315. if (dominatees != null && dominatees.length > 0) {
  316. dt();
  317. print("dominates ");
  318. printClassLinks(dominatees);
  319. }
  320. AspectDoc[] dominators = ad.dominators();
  321. if (dominators != null && dominators.length > 0) {
  322. dt();
  323. print("dominated by ");
  324. printClassLinks(dominators);
  325. }
  326. }
  327. dlEnd();
  328. }
  329. /**
  330. * Prints a list of class links separated by commas.
  331. *
  332. * @param cds array of ClassDoc to be printed.
  333. */
  334. protected void printClassLinks(ClassDoc[] cds) {
  335. if (cds == null || cds.length < 1) return;
  336. for (int i = 0; i < cds.length; i++) {
  337. if (i > 0) print(", ");
  338. if (cds[i] != null) {
  339. printClassLink(cds[i]);
  340. }
  341. }
  342. }
  343. /**
  344. * Prints information about <code>classdoc</code>'s type introduction
  345. * if <code>cd</code>'s type was introduced onto <code>classdoc</code>.
  346. *
  347. * @param cd the ClassDoc being printed.
  348. */
  349. protected void printIntroducedSuper(ClassDoc cd) {
  350. IntroducedSuperDoc[] intros =
  351. ((org.aspectj.ajdoc.ClassDoc)classdoc).introducers();
  352. if (null != intros) {
  353. for (int i = 0; i < intros.length; i++) {
  354. IntroducedSuperDoc intro = intros[i];
  355. org.aspectj.ajdoc.Type[] types = intro.types();
  356. for (int j = 0; j < types.length; j++) {
  357. if (types[j].equals(cd)) {
  358. print(' ');
  359. printText("doclet.by_parens",
  360. getClassLink
  361. (intro.containingClass(),
  362. superIntroductionSubWriter.link(intro),
  363. "introduced"),
  364. getClassLink(intro.containingClass()));
  365. break;
  366. }
  367. }
  368. }
  369. }
  370. }
  371. /**
  372. * Print the navSummaryLink for all the AspectJ subwriters.
  373. */
  374. protected void navAspectJSummaryLinks() {
  375. navSummaryLink(superIntroductionSubWriter);
  376. navSummaryLink(fieldIntroductionSubWriter);
  377. navSummaryLink(constrIntroductionSubWriter);
  378. navSummaryLink(methodIntroductionSubWriter);
  379. navSummaryLink(pointcutSubWriter);
  380. navSummaryLink(adviceSubWriter);
  381. }
  382. /**
  383. * Prints the navSummaryLink correctly.
  384. *
  385. * @param mw AbstractSubWriter to invoke.
  386. */
  387. protected final void navSummaryLink(AbstractSubWriter mw) {
  388. if (mw != null) {
  389. mw.navSummaryLink();
  390. _navGap();
  391. }
  392. }
  393. /**
  394. * Print the navDetailLink for all the AspectJ subwriters.
  395. */
  396. protected void navAspectJDetailLinks() {
  397. navDetailLink(superIntroductionSubWriter);
  398. navDetailLink(fieldIntroductionSubWriter);
  399. navDetailLink(constrIntroductionSubWriter);
  400. navDetailLink(methodIntroductionSubWriter);
  401. navDetailLink(pointcutSubWriter);
  402. navDetailLink(adviceSubWriter);
  403. }
  404. /**
  405. * Prints the navDetailLink correctly.
  406. *
  407. * @param mw AbstractSubWriter to invoke.
  408. */
  409. protected final void navDetailLink(AbstractSubWriter mw) {
  410. if (mw != null) {
  411. mw.navDetailLink();
  412. _navGap();
  413. }
  414. }
  415. /*
  416. * A hack... I'll explain later, if you need to change
  417. * this mail jeffrey_palm@hotmail.com.
  418. */
  419. protected final void _navGap() { super.navGap(); }
  420. protected int navstate = 0;
  421. protected void navGap() {
  422. _navGap();
  423. if (navstate == 1) {
  424. navAspectJSummaryLinks();
  425. navstate++;
  426. } else if (navstate == 3) {
  427. navAspectJDetailLinks();
  428. navstate++;
  429. }
  430. }
  431. protected void printEnclosingClassInfo() {
  432. super.printEnclosingClassInfo();
  433. printAdvisorInfo();
  434. printAdviseeInfo();
  435. }
  436. protected void printAdviseeInfo() {
  437. if (!(classdoc instanceof AspectDoc)) return;
  438. AspectDoc ad = (AspectDoc)classdoc;
  439. Set set = new TreeSet();
  440. AdviceDoc[] as = ad.advice();
  441. if (as != null) {
  442. for (int i = 0; i < as.length; i++) {
  443. ExecutableMemberDoc[] crosscuts = as[i].crosscuts();
  444. if (null != crosscuts) {
  445. for (int j = 0; j < crosscuts.length; j++) {
  446. if (null != crosscuts[j]) {
  447. set.add(crosscuts[j].containingClass());
  448. }
  449. }
  450. }
  451. }
  452. }
  453. IntroductionDoc[] is = ad.introductions();
  454. if (null != is) {
  455. for (int i = 0 ; i < is.length; i++) {
  456. ClassDoc[] targets = is[i].targets();
  457. for (int j = 0; j < targets.length; j++) {
  458. set.add(targets[j]);
  459. }
  460. }
  461. printInfo(set, "doclet.All_Advisees");
  462. }
  463. }
  464. protected void printAdvisorInfo() {
  465. Set set = new TreeSet();
  466. set.addAll(advisors(classdoc.fields()));
  467. set.addAll(advisors(classdoc.methods()));
  468. set.addAll(advisors(classdoc.constructors()));
  469. printInfo(set, "doclet.All_Advisors");
  470. }
  471. protected void printInfo(Collection classdocs, String str) {
  472. if ((null != classdocs) && (classdocs.size() > 0)) {
  473. printInfoHeader();
  474. boldText(str);
  475. dd();
  476. for (Iterator i = classdocs.iterator(); i.hasNext();) {
  477. printClassLink((ClassDoc)i.next());
  478. if (i.hasNext()) print(", ");
  479. }
  480. ddEnd();
  481. dlEnd();
  482. }
  483. }
  484. protected final Collection advisors(final MemberDoc[] ms) {
  485. List list = new ArrayList();
  486. if (null != ms) {
  487. for (int i = 0 ; i < ms.length; i++) {
  488. IntroducedDoc id =
  489. ((org.aspectj.ajdoc.MemberDoc)ms[i]).introduced();
  490. if (id != null) list.add(id.containingClass());
  491. if (ms[i] instanceof org.aspectj.ajdoc.ExecutableMemberDoc) {
  492. AdviceDoc[] as =
  493. ((org.aspectj.ajdoc.ExecutableMemberDoc)ms[i]).advice();
  494. for (int j = 0; j < as.length; j++) {
  495. list.add(as[j].containingClass());
  496. }
  497. }
  498. }
  499. }
  500. return list;
  501. }
  502. }