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.

ClassDocImpl.java 39KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107
  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.ajdoc;
  23. import org.aspectj.ajdoc.IntroducedSuperDoc;
  24. import org.aspectj.ajdoc.PointcutDoc;
  25. import org.aspectj.compiler.base.ast.ClassDec;
  26. import org.aspectj.compiler.base.ast.CodeDec;
  27. import org.aspectj.compiler.base.ast.CompilationUnit;
  28. import org.aspectj.compiler.base.ast.Constructor;
  29. import org.aspectj.compiler.base.ast.ConstructorDec;
  30. import org.aspectj.compiler.base.ast.Dec;
  31. import org.aspectj.compiler.base.ast.Field;
  32. import org.aspectj.compiler.base.ast.FieldDec;
  33. import org.aspectj.compiler.base.ast.Import;
  34. import org.aspectj.compiler.base.ast.Imports;
  35. import org.aspectj.compiler.base.ast.InterfaceDec;
  36. import org.aspectj.compiler.base.ast.Method;
  37. import org.aspectj.compiler.base.ast.NameType;
  38. import org.aspectj.compiler.base.ast.SourceLocation;
  39. import org.aspectj.compiler.base.ast.TextSourceLocation;
  40. import org.aspectj.compiler.base.ast.Type;
  41. import org.aspectj.compiler.base.ast.TypeDec;
  42. import org.aspectj.compiler.crosscuts.AspectJCompiler;
  43. import org.aspectj.compiler.crosscuts.ast.AspectDec;
  44. import org.aspectj.compiler.crosscuts.ast.IntroducedSuperDec;
  45. import org.aspectj.compiler.crosscuts.ast.PointcutSO;
  46. import org.aspectj.ajdoc.ClassDoc;
  47. import com.sun.javadoc.ConstructorDoc;
  48. import com.sun.javadoc.FieldDoc;
  49. import com.sun.javadoc.MethodDoc;
  50. import com.sun.javadoc.PackageDoc;
  51. import java.lang.reflect.Modifier;
  52. import java.util.ArrayList;
  53. import java.util.Collection;
  54. import java.util.Collections;
  55. import java.util.HashMap;
  56. import java.util.Iterator;
  57. import java.util.List;
  58. import java.util.Map;
  59. import java.util.Set;
  60. /**
  61. * This implements ClassDoc and acts as a factory for ClassDocImpl
  62. * and associated DocImpl.
  63. * The factory will excluded new superclasses and introduction classes
  64. * so the caller should take care to include those classes explicitly
  65. * by adding them directly before they are sought indirectly or
  66. * by post-processing them to enable inclusion as appropriate.
  67. */
  68. public class ClassDocImpl
  69. extends ProgramElementDocImpl
  70. implements org.aspectj.ajdoc.ClassDoc {
  71. /**
  72. * Returns an instance of ClassDoc represented by
  73. * the passed in TypeDec.
  74. *
  75. * @param typeDec instance of TypeDec representing
  76. * the ClassDoc that will be returned.
  77. * @return an instance of ClassDoc mirroring
  78. * the passed in TypeDec.
  79. */
  80. public final static ClassDocImpl getInstance(TypeDec typeDec) {
  81. return factory.getInstance(typeDec);
  82. }
  83. /**
  84. * Returns an instance of ClassDoc represented by
  85. * the passed in TypeDec and containing ClassDoc (may be null).
  86. *
  87. * @param outerDoc the containing ClassDoc -- may be null.
  88. * @param typeDec instance of TypeDec representing
  89. * the ClassDoc that will be returned.
  90. * @return an instance of ClassDoc mirroring
  91. * the passed in TypeDec.
  92. */
  93. public final static ClassDocImpl getInstance(ClassDoc outerDoc, TypeDec typeDec) {
  94. return factory.getInstance(outerDoc, typeDec);
  95. }
  96. /**
  97. * Returns the known ClassDocImpl for a given String --
  98. * the returned value may be null.
  99. *
  100. * @return the known ClassDocImpl for a given String --
  101. * the returned value may be null.
  102. */
  103. public final static ClassDocImpl find(String qualifiedName) {
  104. return factory.find(qualifiedName);
  105. }
  106. /**The factory used to create instances of this class. */
  107. private final static Factory factory = new Factory();
  108. /** The ClassDec to which is delegated. */
  109. private final TypeDec typeDec;
  110. // todo: we know these Collections are FilteredDecList, so declare that?
  111. /** The introductions that affect a ClassDoc. */
  112. private Collection introducers;
  113. /** The array of fields visible in this type. */
  114. private Collection fieldDocs;
  115. /** The array of methods visible in this type. */
  116. private Collection methodDocs;
  117. /** The array of constructors visible in this type.
  118. * The implementation must support iterator().remove().
  119. */
  120. private Collection constructorDocs;
  121. /** The array of inner classes visible in thie type. */
  122. private Collection innerclassDocs;
  123. /** The array of interfaces this type implements. */
  124. private Collection interfaceDocs;
  125. /** The array of classes this type imports on demand. */
  126. private Collection importedClasses;
  127. /** The array of package this type imports on demand. */
  128. private Collection importedPackages;
  129. /** The array of pointcuts visible in this type. */
  130. private Collection pointcutDocs;
  131. /** cached variant of <code>((AjdocCompiler)ajc()).getFilter()</code> */
  132. private AccessChecker filter;
  133. /**
  134. * Constructs a representation of an AspectJ-compiled class
  135. * using the underlying TypeDec and containning ClassDoc.
  136. * NOTE: This is protected (and maybe should be private)
  137. * because the static method {@link #getInstance(TypeDec)}
  138. * should always be used to get instances of this type. It
  139. * ensures that enclosing types are created before their
  140. * enclosed types.
  141. *
  142. * @param containingClass ClassDoc that encloses this.
  143. * @param typeDec The underlying TypeDec.
  144. */
  145. protected ClassDocImpl(com.sun.javadoc.ClassDoc containingClass,
  146. TypeDec typeDec) {
  147. super(containingClass);
  148. this.typeDec = typeDec;
  149. //AccessChecker check = getFilter();
  150. // RootDocImpl sets inclusion of world classes
  151. setIncluded(false);
  152. // have to install before creating imports to avoid cycles
  153. factory.put(this, typeDec);
  154. createImports(importedClasses = new ArrayList(),
  155. importedPackages = new ArrayList());
  156. }
  157. /**
  158. * Maps Decs to their counterpart by testing with
  159. * <code>instanceof</code>
  160. *
  161. * @return a MemberDocImpl that has an underlying Dec dec.
  162. */
  163. public MemberDocImpl docForDec(Dec dec) {
  164. if (dec instanceof FieldDec) {
  165. return docForDec((FieldDec)dec);
  166. }
  167. if (dec instanceof CodeDec) {
  168. return docForDec((CodeDec)dec);
  169. }
  170. // todo: map for inner classes, Type, etc?
  171. return null; //TODO error ???
  172. }
  173. /**
  174. * Returns a FieldDocImpl that has an underlying FieldDec dec.
  175. *
  176. * @return a FieldDocImpl that has an underlying FieldDec dec.
  177. */
  178. public FieldDocImpl docForDec(FieldDec dec) {
  179. FieldDoc[] fs = fields();
  180. for (int i = 0; i < fs.length; i++) {
  181. FieldDocImpl fd = (FieldDocImpl)fs[i];
  182. if (fd.dec() == dec) return fd;
  183. }
  184. return null;
  185. }
  186. /**
  187. * Returns a CodeDocImpl that has an underlying CodeDec dec.
  188. *
  189. * @return a CodeDocImpl that has an underlying CodeDec dec.
  190. */
  191. public CodeDocImpl docForDec(CodeDec dec) {
  192. MethodDoc[] ms = methods();
  193. for (int i = 0; i < ms.length; i++) {
  194. CodeDocImpl cd = (CodeDocImpl)ms[i];
  195. if (cd.dec() == dec) return cd;
  196. }
  197. ConstructorDoc[] cs = constructors();
  198. for (int i = 0; i < cs.length; i++) {
  199. CodeDocImpl cd = (CodeDocImpl)cs[i];
  200. if (cd.dec() == dec) return cd;
  201. }
  202. return null;
  203. }
  204. /**
  205. * @todo ??????
  206. */
  207. public TypeDec nonNullTypeDec() {
  208. if (typeDec().getLexicalType() == null) return typeDec();
  209. return super.nonNullTypeDec();
  210. }
  211. /**
  212. * Returns a Collection of ClassDocImpls that have corresponding
  213. * ClassDecs declared within classDec().
  214. *
  215. * @return a Collection of ClassDocImpls that have corresponding
  216. * ClassDecs declared within classDec().
  217. */
  218. private Collection createInnerTypes() {
  219. Collection items = ((NameType)typeDec.getType()).getInnerTypes();
  220. FilteredDecList result =
  221. new FilteredDecList(getFilter(), this);
  222. if (items != null) {
  223. for (Iterator i = items.iterator(); i.hasNext();) {
  224. result.add(((NameType)i.next()).getTypeDec());
  225. }
  226. }
  227. Collections.sort(result);
  228. return result;
  229. }
  230. /**
  231. * Creates the two collection of imports -- class and packages --
  232. * used by the file in which classDec() was declared.
  233. *
  234. * @param importClasses the classes to fill.
  235. * @param importPkgs the packages to fill.
  236. */
  237. private void createImports(final Collection importClasses,
  238. final Collection importPkgs) {
  239. CompilationUnit cu = typeDec.getCompilationUnit();
  240. if (cu != null) {
  241. Imports imports = cu.getImports();
  242. if (imports != null) {
  243. for (int i = 0; i < imports.size(); i++) {
  244. Import imprt = imports.get(i);
  245. if (imprt != null) {
  246. if (imprt.getStar()) {
  247. PackageDoc importedPkg =
  248. PackageDocImpl.getPackageDoc
  249. (imprt.getName());
  250. if (importedPkg != null) {
  251. importPkgs.add(importedPkg);
  252. }
  253. } else {
  254. com.sun.javadoc.ClassDoc importedClass =
  255. findClass(imprt.getName());
  256. if (importedClass != null) {
  257. importClasses.add(importedClass);
  258. }
  259. }
  260. }
  261. }
  262. }
  263. }
  264. }
  265. /**
  266. * Returns a Collection of ClassDocImpl representing the
  267. * interfaces the underlying TypeDec implements.
  268. *
  269. * @return a Collection of ClassDocImpl representing the
  270. * interfaces the underlying TypeDec implements.
  271. */
  272. private Collection createInterfaces() {
  273. //NameType type = (NameType)typeDec.getType();
  274. Collection items = typeDec.getSuperInterfaceTypes();
  275. FilteredDecList result =
  276. new FilteredDecList(getFilter(), this);
  277. if (items != null) {
  278. for (Iterator i = items.iterator(); i.hasNext();) {
  279. result.add(((NameType)i.next()).getTypeDec());
  280. }
  281. }
  282. Collections.sort(result);
  283. return result;
  284. }
  285. /**
  286. * Called by AjdocCompiler to do pruning once the whole world is created.
  287. * This avoids using aspect before initialized when
  288. * this classdoc constructed as a result of aspect
  289. * initialization.
  290. */
  291. void postProcess() {
  292. // prune compiler-generated default constructor if unadvised.
  293. // can't do this on construction since advising aspect may exist but be uninitialized
  294. final SourceLocation parentLoc = dec().getSourceLocation();
  295. final int parentLine = (null == parentLoc ? -1 : parentLoc.getBeginLine());
  296. final int parentColumn = (null == parentLoc ? -1 : parentLoc.getBeginColumn());
  297. if (null == constructorDocs) {
  298. if (null == constructors()) {
  299. // XXX harmless error System.err.println("Unable to post-process");
  300. return;
  301. }
  302. }
  303. try {
  304. //ArrayList removed = new ArrayList();
  305. for (Iterator i = constructorDocs.iterator(); i.hasNext(); ) {
  306. ConstructorDocImpl cdi = (ConstructorDocImpl) i.next();
  307. CodeDec cd = cdi.codeDec();
  308. SourceLocation sl = (null == cd ? null : cd.getSourceLocation());
  309. // if ajc changes so typedec start/end not equal to constructor, then can't recognize
  310. if ((null != sl)
  311. && (parentColumn == sl.getBeginColumn())
  312. && (parentLine == sl.getBeginLine())) {
  313. Object[] advice = cdi.advice();
  314. if ((null != advice) && (1 > advice.length)) {
  315. i.remove();
  316. //removed.add(cdi);
  317. //System.err.println("removing unadvised generated constructor: " + cdi);
  318. } else {
  319. //System.err.println("keeping advised generated constructor: " + cdi);
  320. }
  321. } else {
  322. //System.err.println("keeping ungenerated constructor: " + cdi);
  323. }
  324. }
  325. // for (Iterator i = removed.iterator(); i.hasNext();) {
  326. // Object dec = i.next();
  327. // if (constructorDocs.contains(dec)) {
  328. // throw new Error("remove failed for " + dec);
  329. // }
  330. // }
  331. } catch (UnsupportedOperationException e) {
  332. System.err.println("Warning: ClassDocImpl.constructorDocs not removable");
  333. }
  334. }
  335. /**
  336. * Returns a Collection of ConstructorDocImpl representing the
  337. * constructors the underlying TypeDec declares.
  338. *
  339. * @return a Collection of ConstructorDocImpl representing the
  340. * constructors the underlying TypeDec declares.
  341. */
  342. private Collection createConstructors() {
  343. NameType type = (NameType)typeDec.getType();
  344. Collection items = type.getConstructors();
  345. final SourceLocation parentLoc = dec().getSourceLocation();
  346. final int parentLine = (null == parentLoc ? -1 : parentLoc.getBeginLine());
  347. final int parentColumn = (null == parentLoc ? -1 : parentLoc.getBeginColumn());
  348. FilteredDecList result =
  349. new FilteredDecList(getFilter(), this);
  350. if (items != null) {
  351. for (Iterator i = items.iterator(); i.hasNext();) {
  352. Constructor c = (Constructor) i.next();
  353. ConstructorDec cd = c.getConstructorDec();
  354. ConstructorDocImpl impl = new ConstructorDocImpl(this, cd);
  355. // XXX workaround for ajc bug of default constructor source location
  356. SourceLocation sl = (null == cd ? null : cd.getSourceLocation());
  357. // if line/column starts the same, then a generated constructor
  358. if ((null != sl)
  359. && (parentColumn == sl.getBeginColumn())
  360. && (parentLine == sl.getBeginLine())) {
  361. // use source location clone without comment from class
  362. TextSourceLocation tsl = new TextSourceLocation(sl.getCompilationUnit(),
  363. sl.getStartPosition(), sl.getEndPosition());
  364. tsl.clearComment();
  365. cd.setSourceLocation(tsl);
  366. }
  367. result.add(impl);
  368. }
  369. }
  370. Collections.sort(result);
  371. return result;
  372. }
  373. /**
  374. * Returns a Collection of PointcutDocImpl representing the
  375. * pointcuts the underlying TypeDec declares.
  376. *
  377. * @return a Collection of PointcutDocImpl representing the
  378. * pointcuts the underlying TypeDec declares.
  379. */
  380. private Collection createPointcuts() {
  381. NameType type = (NameType)typeDec.getType();
  382. Collection items = type.getPointcuts();
  383. FilteredDecList result =
  384. new FilteredDecList(getFilter(), this);
  385. if (items != null) {
  386. for (Iterator i = items.iterator(); i.hasNext();) {
  387. result.add(((PointcutSO)i.next()).getPointcutDec());
  388. }
  389. }
  390. Collections.sort(result);
  391. return result;
  392. }
  393. /**
  394. * Returns a Collection of MethodDocImpl representing the
  395. * methods the underlying TypeDec declares.
  396. *
  397. * @return a Collection of MethodDocImpl representing the
  398. * methods the underlying TypeDec declares.
  399. */
  400. private Collection createMethods() {
  401. NameType type = (NameType)typeDec.getType();
  402. Collection methods = type.getMethods();
  403. FilteredDecList result =
  404. new FilteredDecList(getFilter(), this);
  405. if (methods != null) {
  406. for (Iterator i = methods.iterator(); i.hasNext();) {
  407. result.add(((Method)i.next()).getMethodDec());
  408. }
  409. }
  410. Collections.sort(result);
  411. return result;
  412. }
  413. /**
  414. * Returns a Collection of FieldDocImpl representing the
  415. * fields the underlying TypeDec declares.
  416. *
  417. * @return a Collection of FieldDocImpl representing the
  418. * fields the underlying TypeDec declares.
  419. */
  420. private Collection createFields() {
  421. NameType type = (NameType)typeDec.getType();
  422. Collection fields = type.getFields();
  423. FilteredDecList result =
  424. new FilteredDecList(getFilter(), this);
  425. if (fields != null) {
  426. for (Iterator i = fields.iterator(); i.hasNext();) {
  427. result.add(((Field)i.next()).getFieldDec());
  428. }
  429. }
  430. Collections.sort(result);
  431. return result;
  432. }
  433. /** return (and cache) filter from ajc() */
  434. protected AccessChecker getFilter() {
  435. // nb: called during construction
  436. if (null == filter) {
  437. AspectJCompiler ajc = ajc();
  438. if (ajc instanceof AjdocCompiler) {
  439. filter = ((AjdocCompiler) ajc).getFilter();
  440. }
  441. }
  442. return filter; // still may be null
  443. }
  444. /**
  445. * Returns the underlying Dec -- a TypeDec.
  446. *
  447. * @return the underlying Dec -- a TypeDec.
  448. */
  449. protected final Dec dec() {
  450. return typeDec();
  451. }
  452. /**
  453. * Returns the underlying TypeDec.
  454. *
  455. * @return the underlying TypeDec.
  456. */
  457. public final TypeDec typeDec() {
  458. return typeDec;
  459. }
  460. /**
  461. * Returns the fully-qualified name of this TypeDec including
  462. * the package and any enclosing classes.
  463. *
  464. * @return the fully-qualified name of this TypeDec including
  465. * the package and any inclosing classes.
  466. */
  467. public String qualifiedName() {
  468. return qualifiedTypeName().replace('$','.');
  469. }
  470. /**
  471. * Returns the fully-qualfied name of this class.
  472. *
  473. * @return the fully-qualfied name of this class.
  474. */
  475. public String toString() {
  476. return qualifiedName();
  477. }
  478. /**
  479. * Returns the single name of this TypeDec excluding the package
  480. * but including enclosing classes. NOTE: All dollar signs
  481. * are replaced by periods.
  482. *
  483. * @return the single name of this TypeDec excluding the package
  484. * but including enclosing classes.
  485. */
  486. public String name() {
  487. return ((NameType)typeDec().getType()).
  488. getExtendedId().replace('$','.');
  489. }
  490. /**
  491. * Returns the class specified by <code>classname</code>
  492. * from the context of <code>this</code>. This method may return
  493. * <code>null</code> denoting the class wasn't found.
  494. * Search proceeds in the following order:
  495. *
  496. * <ul><ll>
  497. * <li>qualified name</li>
  498. * <li>in this class (inner)</li>
  499. * <li>in this package</li>
  500. * <li>in the class imports</li>
  501. * <li>in the package imports</li>
  502. * </ll></ul>
  503. *
  504. * @return the type specified by <code>classname</code>
  505. * from the context of <code>this</code>.
  506. * @see Util#findClass(ClassDoc,String,JavaCompiler)
  507. * @see <a href="http://java.sun.com/products/jdk/1.2/docs/tooldocs">
  508. * Javadoc Tool Homepage</a>
  509. */
  510. public com.sun.javadoc.ClassDoc findClass(String classname) {
  511. // Sanity check
  512. if (classname == null || classname.length() < 1) {
  513. return null;
  514. }
  515. // The result
  516. com.sun.javadoc.ClassDoc desired;
  517. // [0] The trivial case, the classname is this class
  518. if (classname.equals(name()) ||
  519. classname.equals(qualifiedName())) {
  520. return this;
  521. }
  522. // [1] Look up the fully qualified name.
  523. if ((desired = ClassDocImpl.find(classname)) != null) {
  524. return desired;
  525. }
  526. // [2] Search the inner classes. We can assume that if
  527. // classname refers to an inner class it is unqualified
  528. // with respect to its package, because step [1] would have
  529. // picked it up, then. First look to see if the name
  530. // matches, then search the inner class itself. We check two
  531. // values:
  532. // [1] innername: the unqualified inner class name
  533. // [2] classname: the qualified (with outer class) name
  534. // Example:
  535. // /**
  536. // * @see Inner
  537. // * // classname == Inner (f'cked)
  538. // * // innername == Outer.Inner (ok)
  539. // * @see Outer.Inner
  540. // * // classname == Outer.Inner (ok)
  541. // * // innername == Outer.Outer.Inner (f'cked)
  542. // class Outer {
  543. // static class Inner {}
  544. // }
  545. String innername = name() + '.' + classname;
  546. com.sun.javadoc.ClassDoc[] inners = innerClasses();
  547. if (inners != null) {
  548. for (int i = 0; i < inners.length; i++) {
  549. if (classname.equals(inners[i].name()) ||
  550. innername.equals(inners[i].name())) {
  551. return inners[i];
  552. }
  553. }
  554. }
  555. // [3] Search in this package
  556. if ((desired = containingPackage().findClass(classname)) != null) {
  557. return desired;
  558. }
  559. // [4] Search the class imports. The order for this is specified
  560. // by the compiler -- if you don't believe me read for yourself:
  561. // http://java.sun.com/products/jdk/1.2/docs/tooldocs/win32/ (cont't)
  562. // javadoc.html#seesearchorder
  563. // We don't look in other package, so we assume classname
  564. // is full package-qualified.
  565. com.sun.javadoc.ClassDoc[] imports = importedClasses();
  566. if (imports != null) {
  567. for (int i = 0; i < imports.length; i++) {
  568. if (classname.equals(imports[i].name())) {
  569. return imports[i];
  570. }
  571. }
  572. }
  573. // [5] Search the package imports for the fully-qualified name.
  574. PackageDoc[] pkgs = importedPackages();
  575. if (pkgs != null) {
  576. for (int i = 0; i < pkgs.length; i++) {
  577. if ((desired = pkgs[i].findClass(classname)) != null) {
  578. return desired;
  579. }
  580. }
  581. }
  582. // [5 1/2] OK, I lied above, we do search a couple packages,
  583. // it should be java.lang, but we're aspectj, so we'll look in
  584. // org.aspectj.lang, too. We assume the names are package-unqualified
  585. // in this step.
  586. // TODO: check that this is made final, if not, make it static
  587. String[] pkgnames = {"java.lang", "org.aspectj.lang"};
  588. for (int i = 0; i < pkgnames.length; i++) {
  589. PackageDoc pkg = PackageDocImpl.getPackageDoc(pkgnames[i]);
  590. if (pkg != null) {
  591. if ((desired = pkg.findClass(classname)) != null) {
  592. return desired;
  593. }
  594. }
  595. }
  596. // Found nothing.
  597. return null;
  598. }
  599. /**
  600. * Returns the fields visible in this type.
  601. *
  602. * @return an array of FieldDoc representing
  603. * the fields visible in this type.
  604. */
  605. public FieldDoc[] fields() {
  606. if (fieldDocs == null) {
  607. fieldDocs = createFields();
  608. }
  609. return (FieldDoc[])fieldDocs.toArray
  610. (new org.aspectj.ajdoc.FieldDoc[fieldDocs.size()]);
  611. }
  612. /**
  613. * Returns <code>true</code> is this type is externalizable.
  614. *
  615. * @return <code>true</code> is this type is externalizable.
  616. */
  617. public boolean isExternalizable() {
  618. return false; //TODO
  619. }
  620. /**
  621. * Returns <code>true</code> if this type is serializable.
  622. *
  623. * @return <code>true</code> if this type is serializable.
  624. */
  625. public boolean isSerializable() {
  626. for (Iterator i = typeDec().getSuperInterfaceTypes().iterator();
  627. i.hasNext();) {
  628. if (((Type)i.next()).getId().equals("java.io.Serializable")) {
  629. return true;
  630. }
  631. }
  632. return false;
  633. }
  634. /**
  635. * Returns the methods visible in this type.
  636. *
  637. * @return an array of MethodDoc representing the
  638. * methods visible in this type.
  639. */
  640. public MethodDoc[] methods() {
  641. if (methodDocs == null) {
  642. methodDocs = createMethods();
  643. }
  644. return (MethodDoc[])methodDocs.toArray
  645. (new org.aspectj.ajdoc.MethodDoc[methodDocs.size()]);
  646. }
  647. /**
  648. * Returns the serializable methods visible in this type.
  649. *
  650. * @return an array of MethodDoc representing the
  651. * serializable methods visible in this type.
  652. */
  653. public MethodDoc[] serializationMethods() {
  654. List ser = new ArrayList();
  655. MethodDoc[] mds = methods();
  656. for (int i = 0, N = mds.length; i < N; i++) {
  657. if (mds[i].tags("@serialized").length > 1) ser.add(mds[i]);
  658. }
  659. return (MethodDoc[])ser.toArray(new MethodDoc[ser.size()]);
  660. }
  661. /**
  662. * Returns the serializable fields visible in this type.
  663. *
  664. * @return an array of MethodDoc representing the
  665. * serializable fields visible in this type.
  666. */
  667. public FieldDoc[] serializableFields() {
  668. List ser = new ArrayList();
  669. FieldDoc[] fds = fields();
  670. for (int i = 0, N = fds.length; i < N; i++) {
  671. if (fds[i].serialFieldTags().length > 1) ser.add(fds[i]);
  672. }
  673. return (FieldDoc[])ser.toArray(new FieldDoc[ser.size()]);
  674. }
  675. /**
  676. * Returns <code>true</code> is this type contains
  677. * visible serializable fields.
  678. *
  679. * @return <code>true</code> is this type contains
  680. * visible serializable fields.
  681. */
  682. public boolean definesSerializableFields() {
  683. return serializableFields().length > 0;
  684. }
  685. /**
  686. * Returns the super type of this type. The return value
  687. * is guaranteed to be non-null unless this represents
  688. * java.lang.Object.
  689. *
  690. * @return a ClassDoc representing the super type of this type.
  691. * or null if this represents java.lang.Object.
  692. */
  693. public com.sun.javadoc.ClassDoc superclass() {
  694. if ("java.lang.Object".equals(qualifiedTypeName())) {
  695. return null;
  696. } else {
  697. TypeDec superType = typeDec().getSuperClassType().getTypeDec();
  698. return ClassDocImpl.getInstance(superType);
  699. }
  700. }
  701. /**
  702. * Returns <code>true</code> is <code>c</code> is a
  703. * subtype of <code>this</code>.
  704. *
  705. * @return <code>true</code> is <code>c</code> is a
  706. * subtype of <code>this</code>.
  707. */
  708. public boolean subclassOf(com.sun.javadoc.ClassDoc c) {
  709. return c != null && c.equals(superclass());
  710. }
  711. /**
  712. * Returns the interfaces this type implements.
  713. *
  714. * @return an array of ClassDoc representing the
  715. * interfaces this type implements.
  716. */
  717. public com.sun.javadoc.ClassDoc[] interfaces() {
  718. if (interfaceDocs == null) {
  719. interfaceDocs = createInterfaces();
  720. }
  721. return (ClassDoc[])interfaceDocs.toArray
  722. (new org.aspectj.ajdoc.ClassDoc[interfaceDocs.size()]);
  723. }
  724. /**
  725. * Returns the constructors visible in this type.
  726. *
  727. * @return an array of ConstructorDoc representing the
  728. * visible constructors in this type.
  729. */
  730. public ConstructorDoc[] constructors() {
  731. if (constructorDocs == null) {
  732. constructorDocs = createConstructors();
  733. }
  734. return (ConstructorDoc[])constructorDocs.toArray
  735. (new org.aspectj.ajdoc.ConstructorDoc[constructorDocs.size()]);
  736. }
  737. /**
  738. * Returns the inner class visible in this type.
  739. *
  740. * @return an array of ClassDoc representing the inner
  741. * classes visible in this type.
  742. */
  743. public com.sun.javadoc.ClassDoc[] innerClasses() {
  744. if (innerclassDocs == null) {
  745. innerclassDocs = createInnerTypes();
  746. }
  747. final int size = innerclassDocs.size();
  748. return (ClassDoc[])innerclassDocs.toArray
  749. (new org.aspectj.ajdoc.ClassDoc[size]);
  750. }
  751. /**
  752. * Returns the types imported on demand by this type.
  753. *
  754. * @return an array of ClassDoc representing the
  755. * types imported on demand by this type.
  756. */
  757. public com.sun.javadoc.ClassDoc[] importedClasses() {
  758. return (ClassDoc[])importedClasses.toArray
  759. (new org.aspectj.ajdoc.ClassDoc[importedClasses.size()]);
  760. }
  761. /**
  762. * Returns the packages imported on demand by this type.
  763. *
  764. * @return an array of PackageDoc representing the
  765. * packages imported on demand by this type.
  766. */
  767. public PackageDoc[] importedPackages() {
  768. return (PackageDoc[])importedPackages.toArray
  769. (new org.aspectj.ajdoc.PackageDoc[importedPackages.size()]);
  770. }
  771. /**
  772. * Returns the pointcuts visible in this type.
  773. *
  774. * @return an array of PointcutDoc representing the
  775. * pointcuts visible in this type.
  776. */
  777. public PointcutDoc[] pointcuts() {
  778. if (pointcutDocs == null) {
  779. pointcutDocs = createPointcuts();
  780. }
  781. return (PointcutDoc[])pointcutDocs.toArray
  782. (new PointcutDoc[pointcutDocs.size()]);
  783. }
  784. /**
  785. * Returns <code>true</code> is this type is <code>abstract</code>.
  786. *
  787. * @return <code>true</code> is this type is <code>abstract</code>.
  788. */
  789. public boolean isAbstract() {
  790. return typeDec().isAbstract();
  791. }
  792. /**
  793. * Returns <code>true</code> is this type is as exception.
  794. *
  795. * @return <code>true</code> is this type is an instance
  796. * of java.lang.Exception.
  797. */
  798. public boolean isException() {
  799. //TODO: make lazy
  800. for (com.sun.javadoc.ClassDoc superclass = superclass();
  801. superclass != null &&
  802. !superclass.qualifiedTypeName().equals("java.lang.Object");
  803. superclass = superclass.superclass()) {
  804. if (superclass.qualifiedTypeName().equals("java.lang.Exception")) {
  805. return true;
  806. }
  807. }
  808. return false;
  809. }
  810. /**
  811. * Returns <code>true</code> is this type is an error.
  812. *
  813. * @return <code>true</code> is this type is an instance
  814. * of java.lang.Error.
  815. */
  816. public boolean isError() {
  817. //TODO: make lazy
  818. for (com.sun.javadoc.ClassDoc superclass = superclass();
  819. superclass != null &&
  820. !superclass.qualifiedTypeName().equals("java.lang.Object");
  821. superclass = superclass.superclass()) {
  822. if (superclass.qualifiedTypeName().equals("java.lang.Error")) {
  823. return true;
  824. }
  825. }
  826. return false;
  827. }
  828. /**
  829. * Returns the introductions affecting a ClassDoc's
  830. * type hierarchy.
  831. *
  832. * @return an array of IntroducedSuperDoc representing the
  833. * introductions of this ClassDoc that affect its
  834. * type hierarchy.
  835. */
  836. public IntroducedSuperDoc[] introducers() {
  837. if (introducers == null) {
  838. introducers = createIntroducers();
  839. }
  840. return (IntroducedSuperDoc[])introducers.toArray
  841. (new IntroducedSuperDoc[introducers.size()]);
  842. }
  843. /**
  844. * Returns <code>true</code> is this is an <code>interface</code>.
  845. *
  846. * @return <code>true</code> is this is an <code>interface</code>.
  847. */
  848. public boolean isInterface() {
  849. return typeDec() instanceof InterfaceDec;
  850. }
  851. /**
  852. * Returns <code>true</code> is this is a <code>class</code>.
  853. *
  854. * @return <code>true</code> is this is a <code>class</code>.
  855. */
  856. public boolean isClass() {
  857. return typeDec() instanceof ClassDec;
  858. }
  859. /**
  860. * Returns <code>true</code> is this is an <code>aspect</code>.
  861. *
  862. * @return <code>true</code> is this is an <code>aspect</code>.
  863. */
  864. public boolean isAspect() {
  865. return typeDec() instanceof AspectDec;
  866. }
  867. /**
  868. * Returns <code>true</code> is this class is neither
  869. * an error nor an exception, but this still could be
  870. * an aspect.
  871. *
  872. * @return <code>true</code> is this class is neither
  873. * an error nor an exception, but this still could be
  874. * an aspect.
  875. */
  876. public boolean isOrdinaryClass() {
  877. return isClass() && !(isError() || isException());
  878. }
  879. /**
  880. * Returns int modifiers with the 'interface' bit set.
  881. *
  882. * @return int modifiers with the 'interface' bit set.
  883. * @see java.lang.reflect.Modifier.
  884. */
  885. public int modifierSpecifier() {
  886. return super.modifierSpecifier()
  887. | (isInterface() ? Modifier.INTERFACE : 0);
  888. }
  889. /* ------------------------------------------------------------
  890. * Implementation of Type
  891. * ------------------------------------------------------------
  892. */
  893. /**
  894. * Returns the declaration of this type -- null if
  895. * this isn't included.
  896. *
  897. * @return the ClassDoc represented by this Type or null
  898. * if this isn't included.
  899. */
  900. public com.sun.javadoc.ClassDoc asClassDoc() {
  901. return isIncluded() ? this : null;
  902. }
  903. /**
  904. * Returns this type's dimension information as a String.
  905. *
  906. * @return this type's dimension information as a String.
  907. */
  908. public String dimension() {
  909. return "";
  910. }
  911. /**
  912. * Returns qualified name of type excluding
  913. * any dimension information.
  914. *
  915. * @return qualified name of type excluding
  916. * any dimension information.
  917. */
  918. public String qualifiedTypeName() {
  919. return typeDec().getFullName().replace('$', '.');
  920. }
  921. /**
  922. * Returns unqualified name of type excluding
  923. * any dimension information.
  924. *
  925. * @return unqualified name of type excluding
  926. * any dimension information.
  927. */
  928. public String typeName() {
  929. return typeDec().getId().replace('$', '.');
  930. }
  931. /**
  932. * Returns the Collection of IntroducedSuperDec that
  933. * introduce a type intro this's type hierarchy. At the
  934. * same time, the method makes sure <code>this</code> is
  935. * added to every IntroducedSuperDec's list of targets.
  936. *
  937. * @return Collection of IntroducedSuperDec that
  938. * introduce a type intro this's type hierarchy.
  939. */
  940. private Collection createIntroducers() {
  941. Set affectedBy = ajc().getCorrespondences().getAffectedBy(typeDec);
  942. if (affectedBy.size() < 1) {
  943. return Collections.EMPTY_LIST;
  944. }
  945. Collection list = new ArrayList();
  946. for (Iterator i = affectedBy.iterator(); i.hasNext();) {
  947. Object o = i.next();
  948. if (o instanceof IntroducedSuperDec) {
  949. IntroducedSuperDec dec = (IntroducedSuperDec)o;
  950. TypeDec owner = ((NameType)dec.getDeclaringType()).getTypeDec();
  951. AspectDocImpl ad = (AspectDocImpl)ClassDocImpl.getInstance(owner);
  952. IntroducedSuperDocImpl id = (IntroducedSuperDocImpl)ad.introDocForDec(dec);
  953. list.add(id);
  954. id.addTarget(this);
  955. }
  956. }
  957. return list;
  958. }
  959. /* ------------------------------------------------------------
  960. * Factory instantiation
  961. * ------------------------------------------------------------
  962. */
  963. /**
  964. * Inner class in charge of creating instances of ClassDocImpl.
  965. */
  966. private final static class Factory {
  967. private final Map typeDecsToClassDocs = new HashMap();
  968. private final Map qualifiedNamesToClassDocs = new HashMap();
  969. public final ClassDocImpl find(String qualifiedName) {
  970. return (ClassDocImpl)qualifiedNamesToClassDocs.get(qualifiedName);
  971. }
  972. public final ClassDocImpl getInstance(TypeDec typeDec) {
  973. if (typeDec == null) return null;
  974. ClassDocImpl outerDoc = getInstance(typeDec.getEnclosingTypeDec());
  975. return getInstance(outerDoc, typeDec);
  976. }
  977. public final ClassDocImpl getInstance(ClassDoc outerDoc,
  978. TypeDec typeDec) {
  979. if (typeDec == null) return null;
  980. ClassDocImpl cd = (ClassDocImpl)typeDecsToClassDocs.get(typeDec);
  981. if (cd == null) {
  982. cd = makeInstance(outerDoc, typeDec);
  983. /*
  984. Object o = typeDecsToClassDocs.put(typeDec, cd);
  985. if (null != o) {
  986. throw new Error("new " + cd + " displaced " + o + " for " + typeDec);
  987. }
  988. */
  989. }
  990. return cd;
  991. }
  992. private final ClassDocImpl makeInstance(ClassDoc outerDoc,
  993. TypeDec typeDec) {
  994. ClassDocImpl result = null;
  995. if (typeDec instanceof AspectDec) {
  996. result = new AspectDocImpl(outerDoc, (AspectDec)typeDec);
  997. } else {
  998. result = new ClassDocImpl(outerDoc, typeDec);
  999. }
  1000. if (null == result.containingPackage()) {
  1001. System.err.println("Warning: unable to add "
  1002. + result + " to package");
  1003. }
  1004. return result;
  1005. }
  1006. /**
  1007. * constructor installs itself here before generating imports.
  1008. * fyi: not Thread-safe since available from factory before
  1009. * construction completes
  1010. * @return object displaced, if any - error if not null
  1011. */
  1012. private final Object put(ClassDocImpl classdoc, TypeDec typeDec) {
  1013. Object result = typeDecsToClassDocs.put(typeDec, classdoc);
  1014. if (null == result) {
  1015. result = qualifiedNamesToClassDocs.put(classdoc.qualifiedName(), classdoc);
  1016. }
  1017. return result;
  1018. }
  1019. } // factory
  1020. }