PageRenderTime 59ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 1ms

/src/com/google/doclava/ClassInfo.java

http://doclava.googlecode.com/
Java | 1751 lines | 1398 code | 217 blank | 136 comment | 364 complexity | e47c7301e8d59bf4e25230bc4945f29a MD5 | raw file
Possible License(s): Apache-2.0

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. * Copyright (C) 2010 The Android Open Source Project
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package com.google.doclava;
  17. import com.google.clearsilver.jsilver.data.Data;
  18. import com.sun.javadoc.*;
  19. import java.io.BufferedReader;
  20. import java.io.FileReader;
  21. import java.io.IOException;
  22. import java.util.*;
  23. public class ClassInfo extends DocInfo implements ContainerInfo, Comparable, Scoped {
  24. public static final Comparator<ClassInfo> comparator = new Comparator<ClassInfo>() {
  25. public int compare(ClassInfo a, ClassInfo b) {
  26. return a.name().compareTo(b.name());
  27. }
  28. };
  29. public static final Comparator<ClassInfo> qualifiedComparator = new Comparator<ClassInfo>() {
  30. public int compare(ClassInfo a, ClassInfo b) {
  31. return a.qualifiedName().compareTo(b.qualifiedName());
  32. }
  33. };
  34. /**
  35. * Constructs a stub representation of a class.
  36. */
  37. public ClassInfo(String qualifiedName) {
  38. super("", SourcePositionInfo.UNKNOWN);
  39. mQualifiedName = qualifiedName;
  40. int pos = qualifiedName.lastIndexOf('.');
  41. if (pos != -1) {
  42. mName = qualifiedName.substring(pos + 1);
  43. } else {
  44. mName = qualifiedName;
  45. }
  46. }
  47. public ClassInfo(ClassDoc cl, String rawCommentText, SourcePositionInfo position,
  48. boolean isPublic, boolean isProtected, boolean isPackagePrivate, boolean isPrivate,
  49. boolean isStatic, boolean isInterface, boolean isAbstract, boolean isOrdinaryClass,
  50. boolean isException, boolean isError, boolean isEnum, boolean isAnnotation, boolean isFinal,
  51. boolean isIncluded, String name, String qualifiedName, String qualifiedTypeName,
  52. boolean isPrimitive) {
  53. super(rawCommentText, position);
  54. mClass = cl;
  55. mIsPublic = isPublic;
  56. mIsProtected = isProtected;
  57. mIsPackagePrivate = isPackagePrivate;
  58. mIsPrivate = isPrivate;
  59. mIsStatic = isStatic;
  60. mIsInterface = isInterface;
  61. mIsAbstract = isAbstract;
  62. mIsOrdinaryClass = isOrdinaryClass;
  63. mIsException = isException;
  64. mIsError = isError;
  65. mIsEnum = isEnum;
  66. mIsAnnotation = isAnnotation;
  67. mIsFinal = isFinal;
  68. mIsIncluded = isIncluded;
  69. mName = name;
  70. mQualifiedName = qualifiedName;
  71. mQualifiedTypeName = qualifiedTypeName;
  72. mIsPrimitive = isPrimitive;
  73. mNameParts = name.split("\\.");
  74. }
  75. public void init(TypeInfo typeInfo, ClassInfo[] interfaces, TypeInfo[] interfaceTypes,
  76. ClassInfo[] innerClasses, MethodInfo[] constructors, MethodInfo[] methods,
  77. MethodInfo[] annotationElements, FieldInfo[] fields, FieldInfo[] enumConstants,
  78. PackageInfo containingPackage, ClassInfo containingClass, ClassInfo superclass,
  79. TypeInfo superclassType, AnnotationInstanceInfo[] annotations) {
  80. mTypeInfo = typeInfo;
  81. mRealInterfaces = new ArrayList<ClassInfo>();
  82. for (ClassInfo cl : interfaces) {
  83. mRealInterfaces.add(cl);
  84. }
  85. mRealInterfaceTypes = interfaceTypes;
  86. mInnerClasses = innerClasses;
  87. mAllConstructors = constructors;
  88. mAllSelfMethods = methods;
  89. mAnnotationElements = annotationElements;
  90. mAllSelfFields = fields;
  91. mEnumConstants = enumConstants;
  92. mContainingPackage = containingPackage;
  93. mContainingClass = containingClass;
  94. mRealSuperclass = superclass;
  95. mRealSuperclassType = superclassType;
  96. mAnnotations = annotations;
  97. // after providing new methods and new superclass info,clear any cached
  98. // lists of self + superclass methods, ctors, etc.
  99. mSuperclassInit = false;
  100. mConstructors = null;
  101. mMethods = null;
  102. mSelfMethods = null;
  103. mFields = null;
  104. mSelfFields = null;
  105. mSelfAttributes = null;
  106. mDeprecatedKnown = false;
  107. Arrays.sort(mEnumConstants, FieldInfo.comparator);
  108. Arrays.sort(mInnerClasses, ClassInfo.comparator);
  109. }
  110. public void init2() {
  111. // calling this here forces the AttrTagInfo objects to be linked to the AttribtueInfo
  112. // objects
  113. selfAttributes();
  114. }
  115. public void init3(TypeInfo[] types, ClassInfo[] realInnerClasses) {
  116. mTypeParameters = types;
  117. mRealInnerClasses = realInnerClasses;
  118. }
  119. public ClassInfo[] getRealInnerClasses() {
  120. return mRealInnerClasses;
  121. }
  122. public TypeInfo[] getTypeParameters() {
  123. return mTypeParameters;
  124. }
  125. public boolean checkLevel() {
  126. int val = mCheckLevel;
  127. if (val >= 0) {
  128. return val != 0;
  129. } else {
  130. boolean v =
  131. Doclava.checkLevel(mIsPublic, mIsProtected, mIsPackagePrivate, mIsPrivate, isHidden());
  132. mCheckLevel = v ? 1 : 0;
  133. return v;
  134. }
  135. }
  136. public int compareTo(Object that) {
  137. if (that instanceof ClassInfo) {
  138. return mQualifiedName.compareTo(((ClassInfo) that).mQualifiedName);
  139. } else {
  140. return this.hashCode() - that.hashCode();
  141. }
  142. }
  143. @Override
  144. public ContainerInfo parent() {
  145. return this;
  146. }
  147. public boolean isPublic() {
  148. return mIsPublic;
  149. }
  150. public boolean isProtected() {
  151. return mIsProtected;
  152. }
  153. public boolean isPackagePrivate() {
  154. return mIsPackagePrivate;
  155. }
  156. public boolean isPrivate() {
  157. return mIsPrivate;
  158. }
  159. public boolean isStatic() {
  160. return mIsStatic;
  161. }
  162. public boolean isInterface() {
  163. return mIsInterface;
  164. }
  165. public boolean isAbstract() {
  166. return mIsAbstract;
  167. }
  168. public PackageInfo containingPackage() {
  169. return mContainingPackage;
  170. }
  171. public ClassInfo containingClass() {
  172. return mContainingClass;
  173. }
  174. public boolean isOrdinaryClass() {
  175. return mIsOrdinaryClass;
  176. }
  177. public boolean isException() {
  178. return mIsException;
  179. }
  180. public boolean isError() {
  181. return mIsError;
  182. }
  183. public boolean isEnum() {
  184. return mIsEnum;
  185. }
  186. public boolean isAnnotation() {
  187. return mIsAnnotation;
  188. }
  189. public boolean isFinal() {
  190. return mIsFinal;
  191. }
  192. /**
  193. * Returns true if the class represented by this object is defined
  194. * locally, and thus will be included in local documentation.
  195. */
  196. public boolean isDefinedLocally() {
  197. return mIsIncluded;
  198. }
  199. public HashSet<String> typeVariables() {
  200. HashSet<String> result = TypeInfo.typeVariables(mTypeInfo.typeArguments());
  201. ClassInfo cl = containingClass();
  202. while (cl != null) {
  203. TypeInfo[] types = cl.asTypeInfo().typeArguments();
  204. if (types != null) {
  205. TypeInfo.typeVariables(types, result);
  206. }
  207. cl = cl.containingClass();
  208. }
  209. return result;
  210. }
  211. private static void gatherHiddenInterfaces(ClassInfo cl, HashSet<ClassInfo> interfaces) {
  212. for (ClassInfo iface : cl.mRealInterfaces) {
  213. if (iface.checkLevel()) {
  214. interfaces.add(iface);
  215. } else {
  216. gatherHiddenInterfaces(iface, interfaces);
  217. }
  218. }
  219. }
  220. public ClassInfo[] getInterfaces() {
  221. if (mInterfaces == null) {
  222. if (checkLevel()) {
  223. HashSet<ClassInfo> interfaces = new HashSet<ClassInfo>();
  224. ClassInfo superclass = mRealSuperclass;
  225. while (superclass != null && !superclass.checkLevel()) {
  226. gatherHiddenInterfaces(superclass, interfaces);
  227. superclass = superclass.mRealSuperclass;
  228. }
  229. gatherHiddenInterfaces(this, interfaces);
  230. mInterfaces = interfaces.toArray(new ClassInfo[interfaces.size()]);
  231. } else {
  232. // put something here in case someone uses it
  233. mInterfaces = new ClassInfo[mRealInterfaces.size()];
  234. mRealInterfaces.toArray(mInterfaces);
  235. }
  236. Arrays.sort(mInterfaces, ClassInfo.qualifiedComparator);
  237. }
  238. return mInterfaces;
  239. }
  240. public ClassInfo[] realInterfaces() {
  241. return mRealInterfaces.toArray(new ClassInfo[mRealInterfaces.size()]);
  242. }
  243. TypeInfo[] realInterfaceTypes() {
  244. return mRealInterfaceTypes;
  245. }
  246. public String name() {
  247. return mName;
  248. }
  249. public String[] nameParts() {
  250. return mNameParts;
  251. }
  252. public String leafName() {
  253. return mNameParts[mNameParts.length - 1];
  254. }
  255. public String qualifiedName() {
  256. return mQualifiedName;
  257. }
  258. public String qualifiedTypeName() {
  259. return mQualifiedTypeName;
  260. }
  261. public boolean isPrimitive() {
  262. return mIsPrimitive;
  263. }
  264. public MethodInfo[] allConstructors() {
  265. return mAllConstructors;
  266. }
  267. public MethodInfo[] constructors() {
  268. if (mConstructors == null) {
  269. MethodInfo[] methods = mAllConstructors;
  270. ArrayList<MethodInfo> ctors = new ArrayList<MethodInfo>();
  271. for (int i = 0; i < methods.length; i++) {
  272. MethodInfo m = methods[i];
  273. if (!m.isHidden()) {
  274. ctors.add(m);
  275. }
  276. }
  277. mConstructors = ctors.toArray(new MethodInfo[ctors.size()]);
  278. Arrays.sort(mConstructors, MethodInfo.comparator);
  279. }
  280. return mConstructors;
  281. }
  282. public ClassInfo[] innerClasses() {
  283. return mInnerClasses;
  284. }
  285. public TagInfo[] inlineTags() {
  286. return comment().tags();
  287. }
  288. public TagInfo[] firstSentenceTags() {
  289. return comment().briefTags();
  290. }
  291. public boolean isDeprecated() {
  292. if (!mDeprecatedKnown) {
  293. boolean commentDeprecated = comment().isDeprecated();
  294. boolean annotationDeprecated = false;
  295. for (AnnotationInstanceInfo annotation : annotations()) {
  296. if (annotation.type().qualifiedName().equals("java.lang.Deprecated")) {
  297. annotationDeprecated = true;
  298. break;
  299. }
  300. }
  301. if (commentDeprecated != annotationDeprecated) {
  302. Errors.error(Errors.DEPRECATION_MISMATCH, position(), "Class " + qualifiedName()
  303. + ": @Deprecated annotation and @deprecated comment do not match");
  304. }
  305. mIsDeprecated = commentDeprecated | annotationDeprecated;
  306. mDeprecatedKnown = true;
  307. }
  308. return mIsDeprecated;
  309. }
  310. public TagInfo[] deprecatedTags() {
  311. // Should we also do the interfaces?
  312. return comment().deprecatedTags();
  313. }
  314. public MethodInfo[] methods() {
  315. if (mMethods == null) {
  316. TreeMap<String, MethodInfo> all = new TreeMap<String, MethodInfo>();
  317. ClassInfo[] ifaces = getInterfaces();
  318. for (ClassInfo iface : ifaces) {
  319. if (iface != null) {
  320. MethodInfo[] inhereted = iface.methods();
  321. for (MethodInfo method : inhereted) {
  322. String key = method.getHashableName();
  323. all.put(key, method);
  324. }
  325. }
  326. }
  327. ClassInfo superclass = superclass();
  328. if (superclass != null) {
  329. MethodInfo[] inhereted = superclass.methods();
  330. for (MethodInfo method : inhereted) {
  331. String key = method.getHashableName();
  332. all.put(key, method);
  333. }
  334. }
  335. MethodInfo[] methods = selfMethods();
  336. for (MethodInfo method : methods) {
  337. String key = method.getHashableName();
  338. all.put(key, method);
  339. }
  340. mMethods = all.values().toArray(new MethodInfo[all.size()]);
  341. Arrays.sort(mMethods, MethodInfo.comparator);
  342. }
  343. return mMethods;
  344. }
  345. public MethodInfo[] annotationElements() {
  346. return mAnnotationElements;
  347. }
  348. public AnnotationInstanceInfo[] annotations() {
  349. return mAnnotations;
  350. }
  351. private static void addFields(ClassInfo cl, TreeMap<String, FieldInfo> all) {
  352. FieldInfo[] fields = cl.fields();
  353. int N = fields.length;
  354. for (int i = 0; i < N; i++) {
  355. FieldInfo f = fields[i];
  356. all.put(f.name(), f);
  357. }
  358. }
  359. public FieldInfo[] fields() {
  360. if (mFields == null) {
  361. int N;
  362. TreeMap<String, FieldInfo> all = new TreeMap<String, FieldInfo>();
  363. ClassInfo[] interfaces = getInterfaces();
  364. N = interfaces.length;
  365. for (int i = 0; i < N; i++) {
  366. addFields(interfaces[i], all);
  367. }
  368. ClassInfo superclass = superclass();
  369. if (superclass != null) {
  370. addFields(superclass, all);
  371. }
  372. FieldInfo[] fields = selfFields();
  373. N = fields.length;
  374. for (int i = 0; i < N; i++) {
  375. FieldInfo f = fields[i];
  376. if (!f.isHidden()) {
  377. String key = f.name();
  378. all.put(key, f);
  379. }
  380. }
  381. mFields = all.values().toArray(new FieldInfo[0]);
  382. }
  383. return mFields;
  384. }
  385. public void gatherFields(ClassInfo owner, ClassInfo cl, HashMap<String, FieldInfo> fields) {
  386. FieldInfo[] flds = cl.selfFields();
  387. for (FieldInfo f : flds) {
  388. if (f.checkLevel()) {
  389. fields.put(f.name(), f.cloneForClass(owner));
  390. }
  391. }
  392. }
  393. public FieldInfo[] selfFields() {
  394. if (mSelfFields == null) {
  395. HashMap<String, FieldInfo> fields = new HashMap<String, FieldInfo>();
  396. // our hidden parents
  397. if (mRealSuperclass != null && !mRealSuperclass.checkLevel()) {
  398. gatherFields(this, mRealSuperclass, fields);
  399. }
  400. for (ClassInfo iface : mRealInterfaces) {
  401. if (!iface.checkLevel()) {
  402. gatherFields(this, iface, fields);
  403. }
  404. }
  405. // mine
  406. FieldInfo[] selfFields = mAllSelfFields;
  407. for (int i = 0; i < selfFields.length; i++) {
  408. FieldInfo f = selfFields[i];
  409. if (!f.isHidden()) {
  410. fields.put(f.name(), f);
  411. }
  412. }
  413. // combine and return in
  414. mSelfFields = fields.values().toArray(new FieldInfo[fields.size()]);
  415. Arrays.sort(mSelfFields, FieldInfo.comparator);
  416. }
  417. return mSelfFields;
  418. }
  419. public FieldInfo[] allSelfFields() {
  420. return mAllSelfFields;
  421. }
  422. private void gatherMethods(ClassInfo owner, ClassInfo cl, HashMap<String, MethodInfo> methods) {
  423. MethodInfo[] meth = cl.selfMethods();
  424. for (MethodInfo m : meth) {
  425. if (m.checkLevel()) {
  426. methods.put(m.name() + m.signature(), m.cloneForClass(owner));
  427. }
  428. }
  429. }
  430. public MethodInfo[] selfMethods() {
  431. if (mSelfMethods == null) {
  432. HashMap<String, MethodInfo> methods = new HashMap<String, MethodInfo>();
  433. // our hidden parents
  434. if (mRealSuperclass != null && !mRealSuperclass.checkLevel()) {
  435. gatherMethods(this, mRealSuperclass, methods);
  436. }
  437. for (ClassInfo iface : mRealInterfaces) {
  438. if (!iface.checkLevel()) {
  439. gatherMethods(this, iface, methods);
  440. }
  441. }
  442. // mine
  443. if (mAllSelfMethods != null) {
  444. for (MethodInfo m : mAllSelfMethods) {
  445. if (m.checkLevel()) {
  446. methods.put(m.name() + m.signature(), m);
  447. }
  448. }
  449. }
  450. // combine and return it
  451. mSelfMethods = methods.values().toArray(new MethodInfo[methods.size()]);
  452. Arrays.sort(mSelfMethods, MethodInfo.comparator);
  453. }
  454. return mSelfMethods;
  455. }
  456. public MethodInfo[] allSelfMethods() {
  457. return mAllSelfMethods;
  458. }
  459. public void addMethod(MethodInfo method) {
  460. mApiCheckMethods.put(method.getHashableName(), method);
  461. if (mAllSelfMethods == null) {
  462. mAllSelfMethods = new MethodInfo[] { method };
  463. return;
  464. }
  465. MethodInfo[] methods = new MethodInfo[mAllSelfMethods.length + 1];
  466. int i = 0;
  467. for (MethodInfo m : mAllSelfMethods) {
  468. methods[i++] = m;
  469. }
  470. methods[i] = method;
  471. mAllSelfMethods = methods;
  472. }
  473. public void setContainingPackage(PackageInfo pkg) {
  474. mContainingPackage = pkg;
  475. }
  476. public AttributeInfo[] selfAttributes() {
  477. if (mSelfAttributes == null) {
  478. TreeMap<FieldInfo, AttributeInfo> attrs = new TreeMap<FieldInfo, AttributeInfo>();
  479. // the ones in the class comment won't have any methods
  480. for (AttrTagInfo tag : comment().attrTags()) {
  481. FieldInfo field = tag.reference();
  482. if (field != null) {
  483. AttributeInfo attr = attrs.get(field);
  484. if (attr == null) {
  485. attr = new AttributeInfo(this, field);
  486. attrs.put(field, attr);
  487. }
  488. tag.setAttribute(attr);
  489. }
  490. }
  491. // in the methods
  492. for (MethodInfo m : selfMethods()) {
  493. for (AttrTagInfo tag : m.comment().attrTags()) {
  494. FieldInfo field = tag.reference();
  495. if (field != null) {
  496. AttributeInfo attr = attrs.get(field);
  497. if (attr == null) {
  498. attr = new AttributeInfo(this, field);
  499. attrs.put(field, attr);
  500. }
  501. tag.setAttribute(attr);
  502. attr.methods.add(m);
  503. }
  504. }
  505. }
  506. // constructors too
  507. for (MethodInfo m : constructors()) {
  508. for (AttrTagInfo tag : m.comment().attrTags()) {
  509. FieldInfo field = tag.reference();
  510. if (field != null) {
  511. AttributeInfo attr = attrs.get(field);
  512. if (attr == null) {
  513. attr = new AttributeInfo(this, field);
  514. attrs.put(field, attr);
  515. }
  516. tag.setAttribute(attr);
  517. attr.methods.add(m);
  518. }
  519. }
  520. }
  521. mSelfAttributes = attrs.values().toArray(new AttributeInfo[attrs.size()]);
  522. Arrays.sort(mSelfAttributes, AttributeInfo.comparator);
  523. }
  524. return mSelfAttributes;
  525. }
  526. public FieldInfo[] enumConstants() {
  527. return mEnumConstants;
  528. }
  529. public ClassInfo superclass() {
  530. if (!mSuperclassInit) {
  531. if (this.checkLevel()) {
  532. // rearrange our little inheritance hierarchy, because we need to hide classes that
  533. // don't pass checkLevel
  534. ClassInfo superclass = mRealSuperclass;
  535. while (superclass != null && !superclass.checkLevel()) {
  536. superclass = superclass.mRealSuperclass;
  537. }
  538. mSuperclass = superclass;
  539. } else {
  540. mSuperclass = mRealSuperclass;
  541. }
  542. }
  543. return mSuperclass;
  544. }
  545. public ClassInfo realSuperclass() {
  546. return mRealSuperclass;
  547. }
  548. /**
  549. * always the real superclass, not the collapsed one we get through superclass(), also has the
  550. * type parameter info if it's generic.
  551. */
  552. public TypeInfo superclassType() {
  553. return mRealSuperclassType;
  554. }
  555. public TypeInfo asTypeInfo() {
  556. return mTypeInfo;
  557. }
  558. TypeInfo[] interfaceTypes() {
  559. ClassInfo[] infos = getInterfaces();
  560. int len = infos.length;
  561. TypeInfo[] types = new TypeInfo[len];
  562. for (int i = 0; i < len; i++) {
  563. types[i] = infos[i].asTypeInfo();
  564. }
  565. return types;
  566. }
  567. public String relativePath() {
  568. String s = containingPackage().name();
  569. s = s.replace('.', '/');
  570. s += '/';
  571. s += name();
  572. s += ".html";
  573. return s;
  574. }
  575. public String relativePath(String suffix) {
  576. String s = containingPackage().name();
  577. s = s.replace('.', '/');
  578. s += '/';
  579. s += name() + suffix;
  580. s += ".html";
  581. return s;
  582. }
  583. /** Even indirectly */
  584. public boolean isDerivedFrom(ClassInfo cl) {
  585. ClassInfo dad = this.superclass();
  586. if (dad != null) {
  587. if (dad.equals(cl)) {
  588. return true;
  589. } else {
  590. if (dad.isDerivedFrom(cl)) {
  591. return true;
  592. }
  593. }
  594. }
  595. for (ClassInfo iface : getInterfaces()) {
  596. if (iface.equals(cl)) {
  597. return true;
  598. } else {
  599. if (iface.isDerivedFrom(cl)) {
  600. return true;
  601. }
  602. }
  603. }
  604. return false;
  605. }
  606. public void makeKeywordEntries(List<KeywordEntry> keywords) {
  607. if (!checkLevel()) {
  608. return;
  609. }
  610. String htmlPage = htmlPage();
  611. String qualifiedName = qualifiedName();
  612. keywords.add(new KeywordEntry(name(), htmlPage, "class in " + containingPackage().name()));
  613. FieldInfo[] fields = selfFields();
  614. MethodInfo[] ctors = constructors();
  615. MethodInfo[] methods = selfMethods();
  616. // enum constants
  617. for (FieldInfo field : enumConstants()) {
  618. if (field.checkLevel()) {
  619. keywords.add(new KeywordEntry(field.name(), htmlPage + "#" + field.anchor(),
  620. "enum constant in " + qualifiedName));
  621. }
  622. }
  623. // constants
  624. for (FieldInfo field : fields) {
  625. if (field.isConstant() && field.checkLevel()) {
  626. keywords.add(new KeywordEntry(field.name(), htmlPage + "#" + field.anchor(), "constant in "
  627. + qualifiedName));
  628. }
  629. }
  630. // fields
  631. for (FieldInfo field : fields) {
  632. if (!field.isConstant() && field.checkLevel()) {
  633. keywords.add(new KeywordEntry(field.name(), htmlPage + "#" + field.anchor(), "field in "
  634. + qualifiedName));
  635. }
  636. }
  637. // public constructors
  638. for (MethodInfo m : ctors) {
  639. if (m.isPublic() && m.checkLevel()) {
  640. keywords.add(new KeywordEntry(m.prettySignature(), htmlPage + "#" + m.anchor(),
  641. "constructor in " + qualifiedName));
  642. }
  643. }
  644. // protected constructors
  645. if (Doclava.checkLevel(Doclava.SHOW_PROTECTED)) {
  646. for (MethodInfo m : ctors) {
  647. if (m.isProtected() && m.checkLevel()) {
  648. keywords.add(new KeywordEntry(m.prettySignature(),
  649. htmlPage + "#" + m.anchor(), "constructor in " + qualifiedName));
  650. }
  651. }
  652. }
  653. // package private constructors
  654. if (Doclava.checkLevel(Doclava.SHOW_PACKAGE)) {
  655. for (MethodInfo m : ctors) {
  656. if (m.isPackagePrivate() && m.checkLevel()) {
  657. keywords.add(new KeywordEntry(m.prettySignature(),
  658. htmlPage + "#" + m.anchor(), "constructor in " + qualifiedName));
  659. }
  660. }
  661. }
  662. // private constructors
  663. if (Doclava.checkLevel(Doclava.SHOW_PRIVATE)) {
  664. for (MethodInfo m : ctors) {
  665. if (m.isPrivate() && m.checkLevel()) {
  666. keywords.add(new KeywordEntry(m.name() + m.prettySignature(),
  667. htmlPage + "#" + m.anchor(), "constructor in " + qualifiedName));
  668. }
  669. }
  670. }
  671. // public methods
  672. for (MethodInfo m : methods) {
  673. if (m.isPublic() && m.checkLevel()) {
  674. keywords.add(new KeywordEntry(m.name() + m.prettySignature(), htmlPage + "#" + m.anchor(),
  675. "method in " + qualifiedName));
  676. }
  677. }
  678. // protected methods
  679. if (Doclava.checkLevel(Doclava.SHOW_PROTECTED)) {
  680. for (MethodInfo m : methods) {
  681. if (m.isProtected() && m.checkLevel()) {
  682. keywords.add(new KeywordEntry(m.name() + m.prettySignature(),
  683. htmlPage + "#" + m.anchor(), "method in " + qualifiedName));
  684. }
  685. }
  686. }
  687. // package private methods
  688. if (Doclava.checkLevel(Doclava.SHOW_PACKAGE)) {
  689. for (MethodInfo m : methods) {
  690. if (m.isPackagePrivate() && m.checkLevel()) {
  691. keywords.add(new KeywordEntry(m.name() + m.prettySignature(),
  692. htmlPage + "#" + m.anchor(), "method in " + qualifiedName));
  693. }
  694. }
  695. }
  696. // private methods
  697. if (Doclava.checkLevel(Doclava.SHOW_PRIVATE)) {
  698. for (MethodInfo m : methods) {
  699. if (m.isPrivate() && m.checkLevel()) {
  700. keywords.add(new KeywordEntry(m.name() + m.prettySignature(),
  701. htmlPage + "#" + m.anchor(), "method in " + qualifiedName));
  702. }
  703. }
  704. }
  705. }
  706. public static void makeLinkListHDF(Data data, String base, ClassInfo[] classes) {
  707. final int N = classes.length;
  708. for (int i = 0; i < N; i++) {
  709. ClassInfo cl = classes[i];
  710. if (cl.checkLevel()) {
  711. cl.asTypeInfo().makeHDF(data, base + "." + i);
  712. }
  713. }
  714. }
  715. /**
  716. * Used in lists of this class (packages, nested classes, known subclasses)
  717. */
  718. public void makeShortDescrHDF(Data data, String base) {
  719. mTypeInfo.makeHDF(data, base + ".type");
  720. data.setValue(base + ".kind", this.kind());
  721. TagInfo.makeHDF(data, base + ".shortDescr", this.firstSentenceTags());
  722. TagInfo.makeHDF(data, base + ".deprecated", deprecatedTags());
  723. data.setValue(base + ".since.key", SinceTagger.keyForName(getSince()));
  724. data.setValue(base + ".since.name", getSince());
  725. setFederatedReferences(data, base);
  726. }
  727. /**
  728. * Turns into the main class page
  729. */
  730. public void makeHDF(Data data) {
  731. int i, j, n;
  732. String name = name();
  733. String qualified = qualifiedName();
  734. AttributeInfo[] selfAttributes = selfAttributes();
  735. MethodInfo[] methods = selfMethods();
  736. FieldInfo[] fields = selfFields();
  737. FieldInfo[] enumConstants = enumConstants();
  738. MethodInfo[] ctors = constructors();
  739. ClassInfo[] inners = innerClasses();
  740. // class name
  741. mTypeInfo.makeHDF(data, "class.type");
  742. mTypeInfo.makeQualifiedHDF(data, "class.qualifiedType");
  743. data.setValue("class.name", name);
  744. data.setValue("class.qualified", qualified);
  745. if (isProtected()) {
  746. data.setValue("class.scope", "protected");
  747. } else if (isPublic()) {
  748. data.setValue("class.scope", "public");
  749. }
  750. if (isStatic()) {
  751. data.setValue("class.static", "static");
  752. }
  753. if (isFinal()) {
  754. data.setValue("class.final", "final");
  755. }
  756. if (isAbstract() && !isInterface()) {
  757. data.setValue("class.abstract", "abstract");
  758. }
  759. // class info
  760. String kind = kind();
  761. if (kind != null) {
  762. data.setValue("class.kind", kind);
  763. }
  764. data.setValue("class.since.key", SinceTagger.keyForName(getSince()));
  765. data.setValue("class.since.name", getSince());
  766. setFederatedReferences(data, "class");
  767. // the containing package -- note that this can be passed to type_link,
  768. // but it also contains the list of all of the packages
  769. containingPackage().makeClassLinkListHDF(data, "class.package");
  770. // inheritance hierarchy
  771. Vector<ClassInfo> superClasses = new Vector<ClassInfo>();
  772. superClasses.add(this);
  773. ClassInfo supr = superclass();
  774. while (supr != null) {
  775. superClasses.add(supr);
  776. supr = supr.superclass();
  777. }
  778. n = superClasses.size();
  779. for (i = 0; i < n; i++) {
  780. supr = superClasses.elementAt(n - i - 1);
  781. supr.asTypeInfo().makeQualifiedHDF(data, "class.inheritance." + i + ".class");
  782. supr.asTypeInfo().makeHDF(data, "class.inheritance." + i + ".short_class");
  783. j = 0;
  784. for (TypeInfo t : supr.interfaceTypes()) {
  785. t.makeHDF(data, "class.inheritance." + i + ".interfaces." + j);
  786. j++;
  787. }
  788. }
  789. // class description
  790. TagInfo.makeHDF(data, "class.descr", inlineTags());
  791. TagInfo.makeHDF(data, "class.seeAlso", comment().seeTags());
  792. TagInfo.makeHDF(data, "class.deprecated", deprecatedTags());
  793. // known subclasses
  794. TreeMap<String, ClassInfo> direct = new TreeMap<String, ClassInfo>();
  795. TreeMap<String, ClassInfo> indirect = new TreeMap<String, ClassInfo>();
  796. ClassInfo[] all = Converter.rootClasses();
  797. for (ClassInfo cl : all) {
  798. if (cl.superclass() != null && cl.superclass().equals(this)) {
  799. direct.put(cl.name(), cl);
  800. } else if (cl.isDerivedFrom(this)) {
  801. indirect.put(cl.name(), cl);
  802. }
  803. }
  804. // direct
  805. i = 0;
  806. for (ClassInfo cl : direct.values()) {
  807. if (cl.checkLevel()) {
  808. cl.makeShortDescrHDF(data, "class.subclasses.direct." + i);
  809. }
  810. i++;
  811. }
  812. // indirect
  813. i = 0;
  814. for (ClassInfo cl : indirect.values()) {
  815. if (cl.checkLevel()) {
  816. cl.makeShortDescrHDF(data, "class.subclasses.indirect." + i);
  817. }
  818. i++;
  819. }
  820. // hide special cases
  821. if ("java.lang.Object".equals(qualified) || "java.io.Serializable".equals(qualified)) {
  822. data.setValue("class.subclasses.hidden", "1");
  823. } else {
  824. data.setValue("class.subclasses.hidden", "0");
  825. }
  826. // nested classes
  827. i = 0;
  828. for (ClassInfo inner : inners) {
  829. if (inner.checkLevel()) {
  830. inner.makeShortDescrHDF(data, "class.inners." + i);
  831. }
  832. i++;
  833. }
  834. // enum constants
  835. i = 0;
  836. for (FieldInfo field : enumConstants) {
  837. field.makeHDF(data, "class.enumConstants." + i);
  838. i++;
  839. }
  840. // constants
  841. i = 0;
  842. for (FieldInfo field : fields) {
  843. if (field.isConstant()) {
  844. field.makeHDF(data, "class.constants." + i);
  845. i++;
  846. }
  847. }
  848. // fields
  849. i = 0;
  850. for (FieldInfo field : fields) {
  851. if (!field.isConstant()) {
  852. field.makeHDF(data, "class.fields." + i);
  853. i++;
  854. }
  855. }
  856. // public constructors
  857. i = 0;
  858. for (MethodInfo ctor : ctors) {
  859. if (ctor.isPublic()) {
  860. ctor.makeHDF(data, "class.ctors.public." + i);
  861. i++;
  862. }
  863. }
  864. // protected constructors
  865. if (Doclava.checkLevel(Doclava.SHOW_PROTECTED)) {
  866. i = 0;
  867. for (MethodInfo ctor : ctors) {
  868. if (ctor.isProtected()) {
  869. ctor.makeHDF(data, "class.ctors.protected." + i);
  870. i++;
  871. }
  872. }
  873. }
  874. // package private constructors
  875. if (Doclava.checkLevel(Doclava.SHOW_PACKAGE)) {
  876. i = 0;
  877. for (MethodInfo ctor : ctors) {
  878. if (ctor.isPackagePrivate()) {
  879. ctor.makeHDF(data, "class.ctors.package." + i);
  880. i++;
  881. }
  882. }
  883. }
  884. // private constructors
  885. if (Doclava.checkLevel(Doclava.SHOW_PRIVATE)) {
  886. i = 0;
  887. for (MethodInfo ctor : ctors) {
  888. if (ctor.isPrivate()) {
  889. ctor.makeHDF(data, "class.ctors.private." + i);
  890. i++;
  891. }
  892. }
  893. }
  894. // public methods
  895. i = 0;
  896. for (MethodInfo method : methods) {
  897. if (method.isPublic()) {
  898. method.makeHDF(data, "class.methods.public." + i);
  899. i++;
  900. }
  901. }
  902. // protected methods
  903. if (Doclava.checkLevel(Doclava.SHOW_PROTECTED)) {
  904. i = 0;
  905. for (MethodInfo method : methods) {
  906. if (method.isProtected()) {
  907. method.makeHDF(data, "class.methods.protected." + i);
  908. i++;
  909. }
  910. }
  911. }
  912. // package private methods
  913. if (Doclava.checkLevel(Doclava.SHOW_PACKAGE)) {
  914. i = 0;
  915. for (MethodInfo method : methods) {
  916. if (method.isPackagePrivate()) {
  917. method.makeHDF(data, "class.methods.package." + i);
  918. i++;
  919. }
  920. }
  921. }
  922. // private methods
  923. if (Doclava.checkLevel(Doclava.SHOW_PRIVATE)) {
  924. i = 0;
  925. for (MethodInfo method : methods) {
  926. if (method.isPrivate()) {
  927. method.makeHDF(data, "class.methods.private." + i);
  928. i++;
  929. }
  930. }
  931. }
  932. // xml attributes
  933. i = 0;
  934. for (AttributeInfo attr : selfAttributes) {
  935. if (attr.checkLevel()) {
  936. attr.makeHDF(data, "class.attrs." + i);
  937. i++;
  938. }
  939. }
  940. // inherited methods
  941. Set<ClassInfo> interfaces = new TreeSet<ClassInfo>();
  942. addInterfaces(getInterfaces(), interfaces);
  943. ClassInfo cl = superclass();
  944. i = 0;
  945. while (cl != null) {
  946. addInterfaces(cl.getInterfaces(), interfaces);
  947. makeInheritedHDF(data, i, cl);
  948. cl = cl.superclass();
  949. i++;
  950. }
  951. for (ClassInfo iface : interfaces) {
  952. makeInheritedHDF(data, i, iface);
  953. i++;
  954. }
  955. }
  956. private static void addInterfaces(ClassInfo[] ifaces, Set<ClassInfo> out) {
  957. for (ClassInfo cl : ifaces) {
  958. out.add(cl);
  959. addInterfaces(cl.getInterfaces(), out);
  960. }
  961. }
  962. private static void makeInheritedHDF(Data data, int index, ClassInfo cl) {
  963. int i;
  964. String base = "class.inherited." + index;
  965. data.setValue(base + ".qualified", cl.qualifiedName());
  966. if (cl.checkLevel()) {
  967. data.setValue(base + ".link", cl.htmlPage());
  968. }
  969. String kind = cl.kind();
  970. if (kind != null) {
  971. data.setValue(base + ".kind", kind);
  972. }
  973. if (cl.isDefinedLocally()) {
  974. data.setValue(base + ".included", "true");
  975. } else {
  976. Doclava.federationTagger.tagAll(new ClassInfo[] {cl});
  977. if (!cl.getFederatedReferences().isEmpty()) {
  978. FederatedSite site = cl.getFederatedReferences().iterator().next();
  979. data.setValue(base + ".link", site.linkFor(cl.relativePath()));
  980. data.setValue(base + ".federated", site.name());
  981. }
  982. }
  983. // xml attributes
  984. i = 0;
  985. for (AttributeInfo attr : cl.selfAttributes()) {
  986. attr.makeHDF(data, base + ".attrs." + i);
  987. i++;
  988. }
  989. // methods
  990. i = 0;
  991. for (MethodInfo method : cl.selfMethods()) {
  992. method.makeHDF(data, base + ".methods." + i);
  993. i++;
  994. }
  995. // fields
  996. i = 0;
  997. for (FieldInfo field : cl.selfFields()) {
  998. if (!field.isConstant()) {
  999. field.makeHDF(data, base + ".fields." + i);
  1000. i++;
  1001. }
  1002. }
  1003. // constants
  1004. i = 0;
  1005. for (FieldInfo field : cl.selfFields()) {
  1006. if (field.isConstant()) {
  1007. field.makeHDF(data, base + ".constants." + i);
  1008. i++;
  1009. }
  1010. }
  1011. }
  1012. @Override
  1013. public boolean isHidden() {
  1014. int val = mHidden;
  1015. if (val >= 0) {
  1016. return val != 0;
  1017. } else {
  1018. boolean v = isHiddenImpl();
  1019. mHidden = v ? 1 : 0;
  1020. return v;
  1021. }
  1022. }
  1023. public boolean isHiddenImpl() {
  1024. ClassInfo cl = this;
  1025. while (cl != null) {
  1026. PackageInfo pkg = cl.containingPackage();
  1027. if (pkg != null && pkg.isHidden()) {
  1028. return true;
  1029. }
  1030. if (cl.comment().isHidden()) {
  1031. return true;
  1032. }
  1033. cl = cl.containingClass();
  1034. }
  1035. return false;
  1036. }
  1037. private MethodInfo matchMethod(MethodInfo[] methods, String name, String[] params,
  1038. String[] dimensions, boolean varargs) {
  1039. int len = methods.length;
  1040. for (int i = 0; i < len; i++) {
  1041. MethodInfo method = methods[i];
  1042. if (method.name().equals(name)) {
  1043. if (params == null) {
  1044. return method;
  1045. } else {
  1046. if (method.matchesParams(params, dimensions, varargs)) {
  1047. return method;
  1048. }
  1049. }
  1050. }
  1051. }
  1052. return null;
  1053. }
  1054. public MethodInfo findMethod(String name, String[] params, String[] dimensions, boolean varargs) {
  1055. // first look on our class, and our superclasses
  1056. MethodInfo rv;
  1057. // for methods
  1058. if (mAllSelfMethods != null) {
  1059. rv = matchMethod(methods(), name, params, dimensions, varargs);
  1060. if (rv != null) {
  1061. return rv;
  1062. }
  1063. }
  1064. // for constructors
  1065. if (mAllConstructors != null) {
  1066. rv = matchMethod(constructors(), name, params, dimensions, varargs);
  1067. if (rv != null) {
  1068. return rv;
  1069. }
  1070. }
  1071. // then recursively look at our containing class
  1072. ClassInfo containing = containingClass();
  1073. if (containing != null) {
  1074. return containing.findMethod(name, params, dimensions, varargs);
  1075. }
  1076. return null;
  1077. }
  1078. /**
  1079. * Returns true if the given method's signature is available in this class,
  1080. * either directly or via inheritance.
  1081. */
  1082. public boolean containsMethod(MethodInfo method) {
  1083. for (MethodInfo m : methods()) {
  1084. if (m.getHashableName().equals(method.getHashableName())) {
  1085. return true;
  1086. }
  1087. }
  1088. return false;
  1089. }
  1090. private ClassInfo searchInnerClasses(String[] nameParts, int index) {
  1091. String part = nameParts[index];
  1092. ClassInfo[] inners = mInnerClasses;
  1093. for (ClassInfo in : inners) {
  1094. String[] innerParts = in.nameParts();
  1095. if (part.equals(innerParts[innerParts.length - 1])) {
  1096. if (index == nameParts.length - 1) {
  1097. return in;
  1098. } else {
  1099. return in.searchInnerClasses(nameParts, index + 1);
  1100. }
  1101. }
  1102. }
  1103. return null;
  1104. }
  1105. public ClassInfo extendedFindClass(String className) {
  1106. // ClassDoc.findClass has this bug that we're working around here:
  1107. // If you have a class PackageManager with an inner class PackageInfo
  1108. // and you call it with "PackageInfo" it doesn't find it.
  1109. return searchInnerClasses(className.split("\\."), 0);
  1110. }
  1111. public ClassInfo findClass(String className) {
  1112. return Converter.obtainClass(mClass.findClass(className));
  1113. }
  1114. public ClassInfo findInnerClass(String className) {
  1115. // ClassDoc.findClass won't find inner classes. To deal with that,
  1116. // we try what they gave us first, but if that didn't work, then
  1117. // we see if there are any periods in className, and start searching
  1118. // from there.
  1119. String[] nodes = className.split("\\.");
  1120. ClassDoc cl = mClass;
  1121. for (String n : nodes) {
  1122. cl = cl.findClass(n);
  1123. if (cl == null) {
  1124. return null;
  1125. }
  1126. }
  1127. return Converter.obtainClass(cl);
  1128. }
  1129. public FieldInfo findField(String name) {
  1130. // first look on our class, and our superclasses
  1131. for (FieldInfo f : fields()) {
  1132. if (f.name().equals(name)) {
  1133. return f;
  1134. }
  1135. }
  1136. // then look at our enum constants (these are really fields, maybe
  1137. // they should be mixed into fields(). not sure)
  1138. for (FieldInfo f : enumConstants()) {
  1139. if (f.name().equals(name)) {
  1140. return f;
  1141. }
  1142. }
  1143. // then recursively look at our containing class
  1144. ClassInfo containing = containingClass();
  1145. if (containing != null) {
  1146. return containing.findField(name);
  1147. }
  1148. return null;
  1149. }
  1150. public static ClassInfo[] sortByName(ClassInfo[] classes) {
  1151. int i;
  1152. Sorter[] sorted = new Sorter[classes.length];
  1153. for (i = 0; i < sorted.length; i++) {
  1154. ClassInfo cl = classes[i];
  1155. sorted[i] = new Sorter(cl.name(), cl);
  1156. }
  1157. Arrays.sort(sorted);
  1158. ClassInfo[] rv = new ClassInfo[classes.length];
  1159. for (i = 0; i < rv.length; i++) {
  1160. rv[i] = (ClassInfo) sorted[i].data;
  1161. }
  1162. return rv;
  1163. }
  1164. public boolean equals(ClassInfo that) {
  1165. if (that != null) {
  1166. return this.qualifiedName().equals(that.qualifiedName());
  1167. } else {
  1168. return false;
  1169. }
  1170. }
  1171. public void setNonWrittenConstructors(MethodInfo[] nonWritten) {
  1172. mNonWrittenConstructors = nonWritten;
  1173. }
  1174. public MethodInfo[] getNonWrittenConstructors() {
  1175. return mNonWrittenConstructors;
  1176. }
  1177. public String kind() {
  1178. if (isOrdinaryClass()) {
  1179. return "class";
  1180. } else if (isInterface()) {
  1181. return "interface";
  1182. } else if (isEnum()) {
  1183. return "enum";
  1184. } else if (isError()) {
  1185. return "class";
  1186. } else if (isException()) {
  1187. return "class";
  1188. } else if (isAnnotation()) {
  1189. return "@interface";
  1190. }
  1191. return null;
  1192. }
  1193. public String scope() {
  1194. if (isPublic()) {
  1195. return "public";
  1196. } else if (isProtected()) {
  1197. return "protected";
  1198. } else if (isPackagePrivate()) {
  1199. return "";
  1200. } else if (isPrivate()) {
  1201. return "private";
  1202. } else {
  1203. throw new RuntimeException("invalid scope for object " + this);
  1204. }
  1205. }
  1206. public void setHiddenMethods(MethodInfo[] mInfo) {
  1207. mHiddenMethods = mInfo;
  1208. }
  1209. public MethodInfo[] getHiddenMethods() {
  1210. return mHiddenMethods;
  1211. }
  1212. @Override
  1213. public String toString() {
  1214. return this.qualifiedName();
  1215. }
  1216. public void setReasonIncluded(String reason) {
  1217. mReasonIncluded = reason;
  1218. }
  1219. public String getReasonIncluded() {
  1220. return mReasonIncluded;
  1221. }
  1222. private ClassDoc mClass;
  1223. // ctor
  1224. private boolean mIsPublic;
  1225. private boolean mIsProtected;
  1226. private boolean mIsPackagePrivate;
  1227. private boolean mIsPrivate;
  1228. private boolean mIsStatic;
  1229. private boolean mIsInterface;
  1230. private boolean mIsAbstract;
  1231. private boolean mIsOrdinaryClass;
  1232. private boolean mIsException;
  1233. private boolean mIsError;
  1234. private boolean mIsEnum;
  1235. private boolean mIsAnnotation;
  1236. private boolean mIsFinal;
  1237. private boolean mIsIncluded;
  1238. private String mName;
  1239. private String mQualifiedName;
  1240. private String mQualifiedTypeName;
  1241. private boolean mIsPrimitive;
  1242. private TypeInfo mTypeInfo;
  1243. private String[] mNameParts;
  1244. // init
  1245. private List<ClassInfo> mRealInterfaces = new ArrayList<ClassInfo>();
  1246. private ClassInfo[] mInterfaces;
  1247. private TypeInfo[] mRealInterfaceTypes;
  1248. private ClassInfo[] mInnerClasses;
  1249. private MethodInfo[] mAllConstructors;
  1250. private MethodInfo[] mAllSelfMethods;
  1251. private MethodInfo[] mAnnotationElements; // if this class is an annotation
  1252. private FieldInfo[] mAllSelfFields;
  1253. private FieldInfo[] mEnumConstants;
  1254. private PackageInfo mContainingPackage;
  1255. private ClassInfo mContainingClass;
  1256. private ClassInfo mRealSuperclass;
  1257. private TypeInfo mRealSuperclassType;
  1258. private ClassInfo mSuperclass;
  1259. private AnnotationInstanceInfo[] mAnnotations;
  1260. private boolean mSuperclassInit;
  1261. private boolean mDeprecatedKnown;
  1262. // lazy
  1263. private MethodInfo[] mConstructors;
  1264. private ClassInfo[] mRealInnerClasses;
  1265. private MethodInfo[] mSelfMethods;
  1266. private FieldInfo[] mSelfFields;
  1267. private AttributeInfo[] mSelfAttributes;
  1268. private MethodInfo[] mMethods;
  1269. private FieldInfo[] mFields;
  1270. private TypeInfo[] mTypeParameters;
  1271. private MethodInfo[] mHiddenMethods;
  1272. private int mHidden = -1;
  1273. private int mCheckLevel = -1;
  1274. private String mReasonIncluded;
  1275. private MethodInfo[] mNonWrittenConstructors;
  1276. private boolean mIsDeprecated;
  1277. // TODO: Temporary members from apicheck migration.
  1278. private HashMap<String, MethodInfo> mApiCheckMethods = new HashMap<String, MethodInfo>();
  1279. private HashMap<String, FieldInfo> mApiCheckFields = new HashMap<String, FieldInfo>();
  1280. private HashMap<String, ConstructorInfo> mApiCheckConstructors
  1281. = new HashMap<String, ConstructorInfo>();
  1282. /**
  1283. * Returns true if {@code cl} implements the interface {@code iface} either by either being that
  1284. * interface, implementing that interface or extending a type that implements the interface.
  1285. */
  1286. private boolean implementsInterface(ClassInfo cl, String iface) {
  1287. if (cl.qualifiedName().equals(iface)) {
  1288. return true;
  1289. }
  1290. for (ClassInfo clImplements : cl.getInterfaces()) {
  1291. if (implementsInterface(clImplements, iface)) {
  1292. return true;
  1293. }
  1294. }
  1295. if (cl.mSuperclass != null && implementsInterface(cl.mSuperclass, iface)) {
  1296. return true;
  1297. }
  1298. return false;
  1299. }
  1300. public void addInterface(ClassInfo iface) {
  1301. mRealInterfaces.add(iface);
  1302. }
  1303. public void addConstructor(ConstructorInfo cInfo) {
  1304. mApiCheckConstructors.put(cInfo.getHashableName(), cInfo);
  1305. }
  1306. public void addField(FieldInfo fInfo) {
  1307. mApiCheckFields.put(fInfo.name(), fInfo);
  1308. }
  1309. public void setSuperClass(ClassInfo superclass) {
  1310. mSuperclass = superclass;
  1311. }
  1312. public Map<String, ConstructorInfo> allConstructorsMap() {
  1313. return mApiCheckConstructors;
  1314. }
  1315. public Map<String, FieldInfo> allFields() {
  1316. return mApiCheckFields;
  1317. }
  1318. /**
  1319. * Returns all methods defined directly in this class. For a list of all
  1320. * methods defined by this class and inherited from its supertypes, see
  1321. * {@link #methods()}.
  1322. */
  1323. public Map<String, MethodInfo> allMethods() {
  1324. return mApiCheckMethods;
  1325. }
  1326. /**
  1327. * Returns the class hierarchy for this class, starting with this class.
  1328. */
  1329. public Iterable<ClassInfo> hierarchy() {
  1330. List<ClassInfo> result = new ArrayList<ClassInfo>(4);
  1331. for (ClassInfo c = this; c != null; c = c.mSuperclass) {
  1332. result.add(c);
  1333. }
  1334. return result;
  1335. }
  1336. public String superclassName() {
  1337. if (mSuperclass == null) {
  1338. if (mQualifiedName.equals("java.lang.Object")) {
  1339. return null;
  1340. }
  1341. throw new IllegalStateException("Superclass not set for " + qualifiedName());
  1342. }
  1343. return mSuperclass.mQualifiedName;
  1344. }
  1345. public void setAnnotations(AnnotationInstanceInfo[] annotations) {
  1346. mAnnotations = annotations;
  1347. }
  1348. public boolean isConsistent(ClassInfo cl) {
  1349. boolean consistent = true;
  1350. if (isInterface() != cl.isInterface()) {
  1351. Errors.error(Errors.CHANGED_CLASS, cl.position(), "Class " + cl.qualifiedName()
  1352. + " changed class/interface declaration");
  1353. consistent = false;
  1354. }
  1355. for (ClassInfo iface : mRealInterfaces) {
  1356. if (!implementsInterface(cl, iface.mQualifiedName)) {
  1357. Errors.error(Errors.REMOVED_INTERFACE, cl.position(), "Class " + qualifiedName()
  1358. + " no longer implements " + iface);
  1359. }
  1360. }
  1361. for (ClassInfo iface : cl.mRealInterfaces) {
  1362. if (!implementsInterface(this, iface.mQualifiedName)) {
  1363. Errors.error(Errors.ADDED_INTERFACE, cl.position(), "Added interface " + iface
  1364. + " to class " + qualifiedName());
  1365. consistent = false;
  1366. }
  1367. }
  1368. for (MethodInfo mInfo : mApiCheckMethods.values()) {
  1369. if (cl.mApiCheckMethods.containsKey(mInfo.getHashableName())) {
  1370. if (!mInfo.isConsistent(cl.mApiCheckMethods.get(mInfo.getHashableName()))) {
  1371. consistent = false;
  1372. }
  1373. } else {
  1374. /*
  1375. * This class formerly provided this method directly, and now does not. Check our ancestry
  1376. * to see if there's an inherited version that still fulfills the API requirement.
  1377. */
  1378. MethodInfo mi = ClassInfo.overriddenMethod(mInfo, cl);
  1379. if (mi == null) {
  1380. mi = ClassInfo.interfaceMethod(mInfo, cl);
  1381. }
  1382. if (mi == null) {
  1383. Errors.error(Errors.REMOVED_METHOD, mInfo.position(), "Removed public method "
  1384. + mInfo.qualifiedName());
  1385. consistent = false;
  1386. }
  1387. }
  1388. }
  1389. for (MethodInfo mInfo : cl.mApiCheckMethods.values()) {
  1390. if (!mApiCheckMethods.containsKey(mInfo.getHashableName())) {
  1391. /*
  1392. * Similarly to the above, do not fail if this "new" method is really an override of an
  1393. * existing superclass method.
  1394. */
  1395. MethodInfo mi = ClassInfo.overriddenMethod(mInfo, this);
  1396. if (mi == null) {
  1397. Errors.error(Errors.ADDED_METHOD, mInfo.position(), "Added public method "
  1398. + mInfo.qualifiedName());
  1399. consistent = false;
  1400. }
  1401. }
  1402. }
  1403. for (ConstructorInfo mInfo : mApiCheckConstructors.values()) {
  1404. if (cl.mApiCheckConstructors.containsKey(mInfo.getHashableName())) {
  1405. if (!mInfo.isConsistent(cl.mApiCheckConstructors.get(mInfo.getHashableName()))) {
  1406. consistent = false;
  1407. }
  1408. } else {
  1409. Errors.error(Errors.REMOVED_METHOD, mInfo.position(), "Removed public constructor "
  1410. + mInfo.prettySignature());
  1411. consistent = false;
  1412. }
  1413. }
  1414. for (ConstructorInfo mInfo : cl.mApiCheckConstructors.values()) {
  1415. if (!mApiCheckConstructors.containsKey(mInfo.getHashableName())) {
  1416. Errors.error(Errors.ADDED_METHOD, mInfo.position(), "Added public constructor "
  1417. + mInfo.prettySignature());
  1418. consistent = false;
  1419. }
  1420. }
  1421. for (FieldInfo mInfo : mApiCheckFields.values()) {
  1422. if (cl.mApiCheckFields.containsKey(mInfo.name())) {
  1423. if (!mInfo.isConsistent(cl.mApiCheckFields.get(mInfo.name()))) {
  1424. consistent = false;
  1425. }
  1426. } else {
  1427. Errors.error(Errors.REMOVED_FIELD, mInfo.position(), "Removed field "
  1428. + mInfo.qualifiedName());
  1429. consistent = false;
  1430. }
  1431. }
  1432. for (FieldInfo mInfo : cl.mApiCheckFields.values()) {
  1433. if (!mApiCheckFields.containsKey(mInfo.name())) {
  1434. Errors.error(Errors.ADDED_FIELD, mInfo.position(), "Added public field "
  1435. + mInfo.qualifiedName());
  1436. consistent = false;
  1437. }
  1438. }
  1439. if (mIsAbstract != cl.mIsAbstract) {
  1440. consistent = false;
  1441. Errors.error(Errors.CHANGED_ABSTRACT, cl.position(), "Class " + cl.qualifiedName()
  1442. + " changed abstract qualifier");
  1443. }
  1444. if (mIsFinal != cl.mIsFinal) {
  1445. consistent = false;
  1446. Errors.error(Errors.CHANGED_FINAL, cl.position(), "Class " + cl.qualifiedName()
  1447. + " changed final qualifier");
  1448. }
  1449. if (mIsStatic != cl.mIsStatic) {
  1450. consistent = false;
  1451. Errors.error(Errors.CHANGED_STATIC, cl.position(), "Class " + cl.qualifiedName()
  1452. + " changed static qualifier");
  1453. }
  1454. if (!scope().equals(cl.scope())) {
  1455. consistent = false;
  1456. Errors.error(Errors.CHANGED_SCOPE, cl.position(), "Class " + cl.qualifiedName()
  1457. + " scope changed from " + scope() + " to " + cl.scope());
  1458. }
  1459. if (!isDeprecated() == cl.isDeprecated()) {
  1460. consistent = false;
  1461. Errors.error(Errors.CHANGED_DEPRECATED, cl.position(), "Class " + cl.qualifiedName()
  1462. + " has changed deprecation state");
  1463. }
  1464. if (superclassName() != null) {
  1465. if (cl.superclassName() == null || !superclassName().equals(cl.superclassName())) {
  1466. consistent = false;
  1467. Errors.error(Errors.CHANGED_SUPERCLASS, cl.position(), "Class " + qualifiedName()
  1468. + " superclass changed from " + superclassName() + " to " + cl.superclassName());
  1469. }
  1470. } else if (cl.superclassName() != null) {
  1471. consistent = false;
  1472. Errors.error(Errors.CHANGED_SUPERCLASS, cl.position(), "Class " + qualifiedName()
  1473. + " superclass changed from " + "null to " + cl.superclassName());
  1474. }
  1475. return consistent;
  1476. }
  1477. // Find a superclass implementation of the given method.
  1478. public static MethodInfo overriddenMethod(MethodInfo candidate, ClassInfo newClassObj) {
  1479. if (newClassObj == null) {
  1480. return null;
  1481. }
  1482. for (MethodInfo mi : newClassObj.mApiCheckMethods.values()) {
  1483. if (mi.matches(candidate)) {
  1484. // found it
  1485. return mi;
  1486. }
  1487. }
  1488. // not found here. recursively search ancestors
  1489. return ClassInfo.overriddenMethod(candidate, newClassObj.mSuperclass);
  1490. }
  1491. // Find a superinterface declaration of the given method.
  1492. public static MethodInfo interfaceMethod(MethodInfo candidate, ClassInfo newClassObj) {
  1493. if (newClassObj == null) {
  1494. return null;
  1495. }
  1496. for (ClassInfo interfaceInfo : newClassObj.getInterfaces()) {
  1497. for (MethodInfo mi : interfaceInfo.mApiCheckMethods.values()) {
  1498. if (mi.matches(candidate)) {
  1499. return mi;
  1500. }
  1501. }
  1502. }
  1503. return ClassInfo.interfaceMethod(candidate, newClassObj.mSuperclass);
  1504. }
  1505. public boolean hasConstructor(MethodInfo constructor) {
  1506. String name = constructor.getHashableName();
  1507. for (ConstructorInfo ctor : mApiCheckConstructors.values()) {
  1508. if (name.equals(ctor.getHashableName())) {
  1509. return true;
  1510. }
  1511. }
  1512. return false;
  1513. }
  1514. public void setTypeInfo(TypeInfo typeInfo) {
  1515. mTypeInfo = typeInfo;
  1516. }
  1517. public String getSource() throws IOException {
  1518. StringBuffer stringBuffer = new StringBuffer();
  1519. BufferedReader reader;
  1520. reader = new BufferedReader(new FileReader(mPosition.file));
  1521. String line = null;
  1522. while ((line = reader.readLine()) != null) {
  1523. stringBuffer.append(line)
  1524. .append(System.getProperty("line.separator"));
  1525. }
  1526. try {

Large files files are truncated, but you can click here to view the full file