blob: 7f96b806c2279a5112c23de9acc11f25cb1dd56c [file] [log] [blame]
The Android Open Source Project88b60792009-03-03 19:28:42 -08001/*
2 * Copyright (C) 2008 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
17import org.clearsilver.HDF;
Jesse Wilson5e0dd412009-06-01 17:59:44 -070018
The Android Open Source Project88b60792009-03-03 19:28:42 -080019import java.util.*;
The Android Open Source Project88b60792009-03-03 19:28:42 -080020
21public class MethodInfo extends MemberInfo
22{
23 public static final Comparator<MethodInfo> comparator = new Comparator<MethodInfo>() {
24 public int compare(MethodInfo a, MethodInfo b) {
25 return a.name().compareTo(b.name());
26 }
27 };
Xavier Ducrohet5ee390d2009-09-10 13:08:27 -070028
The Android Open Source Project88b60792009-03-03 19:28:42 -080029 private class InlineTags implements InheritedTags
Xavier Ducrohet5ee390d2009-09-10 13:08:27 -070030 {
The Android Open Source Project88b60792009-03-03 19:28:42 -080031 public TagInfo[] tags()
32 {
33 return comment().tags();
34 }
35 public InheritedTags inherited()
36 {
37 MethodInfo m = findOverriddenMethod(name(), signature());
38 if (m != null) {
39 return m.inlineTags();
40 } else {
41 return null;
42 }
43 }
44 }
Xavier Ducrohet5ee390d2009-09-10 13:08:27 -070045
The Android Open Source Project88b60792009-03-03 19:28:42 -080046 private static void addInterfaces(ClassInfo[] ifaces, ArrayList<ClassInfo> queue)
47 {
48 for (ClassInfo i: ifaces) {
49 queue.add(i);
50 }
51 for (ClassInfo i: ifaces) {
52 addInterfaces(i.interfaces(), queue);
53 }
54 }
55
56 // first looks for a superclass, and then does a breadth first search to
57 // find the least far away match
58 public MethodInfo findOverriddenMethod(String name, String signature)
59 {
60 if (mReturnType == null) {
61 // ctor
62 return null;
63 }
64 if (mOverriddenMethod != null) {
65 return mOverriddenMethod;
66 }
67
68 ArrayList<ClassInfo> queue = new ArrayList<ClassInfo>();
69 addInterfaces(containingClass().interfaces(), queue);
70 for (ClassInfo iface: queue) {
71 for (MethodInfo me: iface.methods()) {
72 if (me.name().equals(name)
73 && me.signature().equals(signature)
74 && me.inlineTags().tags() != null
75 && me.inlineTags().tags().length > 0) {
76 return me;
77 }
78 }
79 }
80 return null;
81 }
Xavier Ducrohet5ee390d2009-09-10 13:08:27 -070082
The Android Open Source Project88b60792009-03-03 19:28:42 -080083 private static void addRealInterfaces(ClassInfo[] ifaces, ArrayList<ClassInfo> queue)
84 {
85 for (ClassInfo i: ifaces) {
86 queue.add(i);
87 if (i.realSuperclass() != null && i.realSuperclass().isAbstract()) {
88 queue.add(i.superclass());
89 }
90 }
91 for (ClassInfo i: ifaces) {
92 addInterfaces(i.realInterfaces(), queue);
93 }
94 }
Xavier Ducrohet5ee390d2009-09-10 13:08:27 -070095
The Android Open Source Project88b60792009-03-03 19:28:42 -080096 public MethodInfo findRealOverriddenMethod(String name, String signature, HashSet notStrippable) {
97 if (mReturnType == null) {
98 // ctor
99 return null;
100 }
101 if (mOverriddenMethod != null) {
102 return mOverriddenMethod;
103 }
104
105 ArrayList<ClassInfo> queue = new ArrayList<ClassInfo>();
Xavier Ducrohet5ee390d2009-09-10 13:08:27 -0700106 if (containingClass().realSuperclass() != null &&
The Android Open Source Project88b60792009-03-03 19:28:42 -0800107 containingClass().realSuperclass().isAbstract()) {
108 queue.add(containingClass());
109 }
110 addInterfaces(containingClass().realInterfaces(), queue);
111 for (ClassInfo iface: queue) {
112 for (MethodInfo me: iface.methods()) {
113 if (me.name().equals(name)
114 && me.signature().equals(signature)
115 && me.inlineTags().tags() != null
116 && me.inlineTags().tags().length > 0
117 && notStrippable.contains(me.containingClass())) {
118 return me;
119 }
120 }
121 }
122 return null;
123 }
Xavier Ducrohet5ee390d2009-09-10 13:08:27 -0700124
The Android Open Source Project88b60792009-03-03 19:28:42 -0800125 public MethodInfo findSuperclassImplementation(HashSet notStrippable) {
126 if (mReturnType == null) {
127 // ctor
128 return null;
129 }
130 if (mOverriddenMethod != null) {
131 // Even if we're told outright that this was the overridden method, we want to
132 // be conservative and ignore mismatches of parameter types -- they arise from
133 // extending generic specializations, and we want to consider the derived-class
134 // method to be a non-override.
135 if (this.signature().equals(mOverriddenMethod.signature())) {
136 return mOverriddenMethod;
137 }
138 }
139
140 ArrayList<ClassInfo> queue = new ArrayList<ClassInfo>();
Xavier Ducrohet5ee390d2009-09-10 13:08:27 -0700141 if (containingClass().realSuperclass() != null &&
The Android Open Source Project88b60792009-03-03 19:28:42 -0800142 containingClass().realSuperclass().isAbstract()) {
143 queue.add(containingClass());
144 }
145 addInterfaces(containingClass().realInterfaces(), queue);
146 for (ClassInfo iface: queue) {
147 for (MethodInfo me: iface.methods()) {
148 if (me.name().equals(this.name())
149 && me.signature().equals(this.signature())
150 && notStrippable.contains(me.containingClass())) {
151 return me;
152 }
153 }
154 }
155 return null;
156 }
Xavier Ducrohet5ee390d2009-09-10 13:08:27 -0700157
The Android Open Source Project88b60792009-03-03 19:28:42 -0800158 public ClassInfo findRealOverriddenClass(String name, String signature) {
159 if (mReturnType == null) {
160 // ctor
161 return null;
162 }
163 if (mOverriddenMethod != null) {
164 return mOverriddenMethod.mRealContainingClass;
165 }
166
167 ArrayList<ClassInfo> queue = new ArrayList<ClassInfo>();
Xavier Ducrohet5ee390d2009-09-10 13:08:27 -0700168 if (containingClass().realSuperclass() != null &&
The Android Open Source Project88b60792009-03-03 19:28:42 -0800169 containingClass().realSuperclass().isAbstract()) {
170 queue.add(containingClass());
171 }
172 addInterfaces(containingClass().realInterfaces(), queue);
173 for (ClassInfo iface: queue) {
174 for (MethodInfo me: iface.methods()) {
175 if (me.name().equals(name)
176 && me.signature().equals(signature)
177 && me.inlineTags().tags() != null
178 && me.inlineTags().tags().length > 0) {
179 return iface;
180 }
181 }
182 }
183 return null;
184 }
185
186 private class FirstSentenceTags implements InheritedTags
187 {
188 public TagInfo[] tags()
189 {
190 return comment().briefTags();
191 }
192 public InheritedTags inherited()
193 {
194 MethodInfo m = findOverriddenMethod(name(), signature());
195 if (m != null) {
196 return m.firstSentenceTags();
197 } else {
198 return null;
199 }
200 }
201 }
Xavier Ducrohet5ee390d2009-09-10 13:08:27 -0700202
The Android Open Source Project88b60792009-03-03 19:28:42 -0800203 private class ReturnTags implements InheritedTags {
204 public TagInfo[] tags() {
205 return comment().returnTags();
206 }
207 public InheritedTags inherited() {
208 MethodInfo m = findOverriddenMethod(name(), signature());
209 if (m != null) {
210 return m.returnTags();
211 } else {
212 return null;
213 }
214 }
215 }
Xavier Ducrohet5ee390d2009-09-10 13:08:27 -0700216
The Android Open Source Project88b60792009-03-03 19:28:42 -0800217 public boolean isDeprecated() {
218 boolean deprecated = false;
219 if (!mDeprecatedKnown) {
220 boolean commentDeprecated = (comment().deprecatedTags().length > 0);
221 boolean annotationDeprecated = false;
222 for (AnnotationInstanceInfo annotation : annotations()) {
223 if (annotation.type().qualifiedName().equals("java.lang.Deprecated")) {
224 annotationDeprecated = true;
225 break;
226 }
227 }
228
229 if (commentDeprecated != annotationDeprecated) {
230 Errors.error(Errors.DEPRECATION_MISMATCH, position(),
231 "Method " + mContainingClass.qualifiedName() + "." + name()
232 + ": @Deprecated annotation and @deprecated doc tag do not match");
233 }
234
235 mIsDeprecated = commentDeprecated | annotationDeprecated;
236 mDeprecatedKnown = true;
237 }
238 return mIsDeprecated;
239 }
Xavier Ducrohet5ee390d2009-09-10 13:08:27 -0700240
The Android Open Source Project88b60792009-03-03 19:28:42 -0800241 public TypeInfo[] getTypeParameters(){
242 return mTypeParameters;
243 }
244
245 public MethodInfo cloneForClass(ClassInfo newContainingClass) {
246 MethodInfo result = new MethodInfo(getRawCommentText(), mTypeParameters,
247 name(), signature(), newContainingClass, realContainingClass(),
248 isPublic(), isProtected(), isPackagePrivate(), isPrivate(), isFinal(), isStatic(),
249 isSynthetic(), mIsAbstract, mIsSynchronized, mIsNative, mIsAnnotationElement,
250 kind(), mFlatSignature, mOverriddenMethod,
251 mReturnType, mParameters, mThrownExceptions, position(), annotations());
252 result.init(mDefaultAnnotationElementValue);
253 return result;
254 }
255
256 public MethodInfo(String rawCommentText, TypeInfo[] typeParameters, String name,
257 String signature, ClassInfo containingClass, ClassInfo realContainingClass,
258 boolean isPublic, boolean isProtected,
259 boolean isPackagePrivate, boolean isPrivate,
260 boolean isFinal, boolean isStatic, boolean isSynthetic,
261 boolean isAbstract, boolean isSynchronized, boolean isNative,
262 boolean isAnnotationElement, String kind,
263 String flatSignature, MethodInfo overriddenMethod,
264 TypeInfo returnType, ParameterInfo[] parameters,
265 ClassInfo[] thrownExceptions, SourcePositionInfo position,
266 AnnotationInstanceInfo[] annotations)
267 {
268 // Explicitly coerce 'final' state of Java6-compiled enum values() method, to match
269 // the Java5-emitted base API description.
270 super(rawCommentText, name, signature, containingClass, realContainingClass,
271 isPublic, isProtected, isPackagePrivate, isPrivate,
272 ((name.equals("values") && containingClass.isEnum()) ? true : isFinal),
273 isStatic, isSynthetic, kind, position, annotations);
274
275 // The underlying MethodDoc for an interface's declared methods winds up being marked
276 // non-abstract. Correct that here by looking at the immediate-parent class, and marking
Xavier Ducrohet5ee390d2009-09-10 13:08:27 -0700277 // this method abstract if it is an unimplemented interface method.
The Android Open Source Project88b60792009-03-03 19:28:42 -0800278 if (containingClass.isInterface()) {
279 isAbstract = true;
280 }
281
282 mReasonOpened = "0:0";
283 mIsAnnotationElement = isAnnotationElement;
284 mTypeParameters = typeParameters;
285 mIsAbstract = isAbstract;
286 mIsSynchronized = isSynchronized;
287 mIsNative = isNative;
288 mFlatSignature = flatSignature;
289 mOverriddenMethod = overriddenMethod;
290 mReturnType = returnType;
291 mParameters = parameters;
292 mThrownExceptions = thrownExceptions;
293 }
294
295 public void init(AnnotationValueInfo defaultAnnotationElementValue)
296 {
297 mDefaultAnnotationElementValue = defaultAnnotationElementValue;
298 }
299
300 public boolean isAbstract()
301 {
302 return mIsAbstract;
303 }
304
305 public boolean isSynchronized()
306 {
307 return mIsSynchronized;
308 }
309
310 public boolean isNative()
311 {
312 return mIsNative;
313 }
314
315 public String flatSignature()
316 {
317 return mFlatSignature;
318 }
319
320 public InheritedTags inlineTags()
321 {
322 return new InlineTags();
323 }
324
325 public InheritedTags firstSentenceTags()
326 {
327 return new FirstSentenceTags();
328 }
329
330 public InheritedTags returnTags() {
331 return new ReturnTags();
332 }
333
334 public TypeInfo returnType()
335 {
336 return mReturnType;
337 }
338
339 public String prettySignature()
340 {
341 String s = "(";
342 int N = mParameters.length;
343 for (int i=0; i<N; i++) {
344 ParameterInfo p = mParameters[i];
345 TypeInfo t = p.type();
346 if (t.isPrimitive()) {
347 s += t.simpleTypeName();
348 } else {
349 s += t.asClassInfo().name();
350 }
351 if (i != N-1) {
352 s += ',';
353 }
354 }
355 s += ')';
356 return s;
357 }
358
Jesse Wilson5e0dd412009-06-01 17:59:44 -0700359 /**
360 * Returns a name consistent with the {@link
361 * com.android.apicheck.MethodInfo#getHashableName()}.
362 */
363 public String getHashableName() {
364 StringBuilder result = new StringBuilder();
365 result.append(name());
Jesse Wilson90c1d532009-08-11 16:36:42 -0700366 for (int p = 0; p < mParameters.length; p++) {
367 result.append(":");
368 if (p == mParameters.length - 1 && isVarArgs()) {
369 // TODO: note that this does not attempt to handle hypothetical
370 // vararg methods whose last parameter is a list of arrays, e.g.
371 // "Object[]...".
372 result.append(mParameters[p].type().fullNameNoDimension(typeVariables()))
373 .append("...");
374 } else {
375 result.append(mParameters[p].type().fullName(typeVariables()));
376 }
Jesse Wilson5e0dd412009-06-01 17:59:44 -0700377 }
378 return result.toString();
379 }
380
The Android Open Source Project88b60792009-03-03 19:28:42 -0800381 private boolean inList(ClassInfo item, ThrowsTagInfo[] list)
382 {
383 int len = list.length;
384 String qn = item.qualifiedName();
385 for (int i=0; i<len; i++) {
386 ClassInfo ex = list[i].exception();
387 if (ex != null && ex.qualifiedName().equals(qn)) {
388 return true;
389 }
390 }
391 return false;
392 }
393
394 public ThrowsTagInfo[] throwsTags()
395 {
396 if (mThrowsTags == null) {
397 ThrowsTagInfo[] documented = comment().throwsTags();
398 ArrayList<ThrowsTagInfo> rv = new ArrayList<ThrowsTagInfo>();
399
400 int len = documented.length;
401 for (int i=0; i<len; i++) {
402 rv.add(documented[i]);
403 }
404
405 ClassInfo[] all = mThrownExceptions;
406 len = all.length;
407 for (int i=0; i<len; i++) {
408 ClassInfo cl = all[i];
409 if (documented == null || !inList(cl, documented)) {
410 rv.add(new ThrowsTagInfo("@throws", "@throws",
411 cl.qualifiedName(), cl, "",
412 containingClass(), position()));
413 }
414 }
415 mThrowsTags = rv.toArray(new ThrowsTagInfo[rv.size()]);
416 }
417 return mThrowsTags;
418 }
419
420 private static int indexOfParam(String name, String[] list)
421 {
422 final int N = list.length;
423 for (int i=0; i<N; i++) {
424 if (name.equals(list[i])) {
425 return i;
426 }
427 }
428 return -1;
429 }
430
431 public ParamTagInfo[] paramTags()
432 {
433 if (mParamTags == null) {
434 final int N = mParameters.length;
435
436 String[] names = new String[N];
437 String[] comments = new String[N];
438 SourcePositionInfo[] positions = new SourcePositionInfo[N];
439
440 // get the right names so we can handle our names being different from
441 // our parent's names.
442 for (int i=0; i<N; i++) {
443 names[i] = mParameters[i].name();
444 comments[i] = "";
445 positions[i] = mParameters[i].position();
446 }
447
448 // gather our comments, and complain about misnamed @param tags
449 for (ParamTagInfo tag: comment().paramTags()) {
450 int index = indexOfParam(tag.parameterName(), names);
451 if (index >= 0) {
452 comments[index] = tag.parameterComment();
453 positions[index] = tag.position();
454 } else {
455 Errors.error(Errors.UNKNOWN_PARAM_TAG_NAME, tag.position(),
456 "@param tag with name that doesn't match the parameter list: '"
457 + tag.parameterName() + "'");
458 }
459 }
Xavier Ducrohet5ee390d2009-09-10 13:08:27 -0700460
The Android Open Source Project88b60792009-03-03 19:28:42 -0800461 // get our parent's tags to fill in the blanks
462 MethodInfo overridden = this.findOverriddenMethod(name(), signature());
463 if (overridden != null) {
464 ParamTagInfo[] maternal = overridden.paramTags();
465 for (int i=0; i<N; i++) {
466 if (comments[i].equals("")) {
467 comments[i] = maternal[i].parameterComment();
468 positions[i] = maternal[i].position();
469 }
470 }
471 }
472
473 // construct the results, and cache them for next time
474 mParamTags = new ParamTagInfo[N];
475 for (int i=0; i<N; i++) {
476 mParamTags[i] = new ParamTagInfo("@param", "@param", names[i] + " " + comments[i],
477 parent(), positions[i]);
478
479 // while we're here, if we find any parameters that are still undocumented at this
480 // point, complain. (this warning is off by default, because it's really, really
481 // common; but, it's good to be able to enforce it)
482 if (comments[i].equals("")) {
483 Errors.error(Errors.UNDOCUMENTED_PARAMETER, positions[i],
484 "Undocumented parameter '" + names[i] + "' on method '"
485 + name() + "'");
486 }
487 }
488 }
489 return mParamTags;
490 }
491
492 public SeeTagInfo[] seeTags()
493 {
494 SeeTagInfo[] result = comment().seeTags();
495 if (result == null) {
496 if (mOverriddenMethod != null) {
497 result = mOverriddenMethod.seeTags();
498 }
499 }
500 return result;
501 }
502
503 public TagInfo[] deprecatedTags()
504 {
505 TagInfo[] result = comment().deprecatedTags();
506 if (result.length == 0) {
507 if (comment().undeprecateTags().length == 0) {
508 if (mOverriddenMethod != null) {
509 result = mOverriddenMethod.deprecatedTags();
510 }
511 }
512 }
513 return result;
514 }
515
516 public ParameterInfo[] parameters()
517 {
518 return mParameters;
519 }
Xavier Ducrohet5ee390d2009-09-10 13:08:27 -0700520
The Android Open Source Project88b60792009-03-03 19:28:42 -0800521
522 public boolean matchesParams(String[] params, String[] dimensions)
523 {
524 if (mParamStrings == null) {
525 ParameterInfo[] mine = mParameters;
526 int len = mine.length;
527 if (len != params.length) {
528 return false;
529 }
530 for (int i=0; i<len; i++) {
531 TypeInfo t = mine[i].type();
532 if (!t.dimension().equals(dimensions[i])) {
533 return false;
534 }
535 String qn = t.qualifiedTypeName();
536 String s = params[i];
537 int slen = s.length();
538 int qnlen = qn.length();
539 if (!(qn.equals(s) ||
540 ((slen+1)<qnlen && qn.charAt(qnlen-slen-1)=='.'
541 && qn.endsWith(s)))) {
542 return false;
543 }
544 }
545 }
546 return true;
547 }
548
549 public void makeHDF(HDF data, String base)
550 {
551 data.setValue(base + ".kind", kind());
552 data.setValue(base + ".name", name());
553 data.setValue(base + ".href", htmlPage());
554 data.setValue(base + ".anchor", anchor());
555
556 if (mReturnType != null) {
557 returnType().makeHDF(data, base + ".returnType", false, typeVariables());
558 data.setValue(base + ".abstract", mIsAbstract ? "abstract" : "");
559 }
560
561 data.setValue(base + ".synchronized", mIsSynchronized ? "synchronized" : "");
562 data.setValue(base + ".final", isFinal() ? "final" : "");
563 data.setValue(base + ".static", isStatic() ? "static" : "");
564
565 TagInfo.makeHDF(data, base + ".shortDescr", firstSentenceTags());
566 TagInfo.makeHDF(data, base + ".descr", inlineTags());
567 TagInfo.makeHDF(data, base + ".deprecated", deprecatedTags());
568 TagInfo.makeHDF(data, base + ".seeAlso", seeTags());
Jesse Wilson5e0dd412009-06-01 17:59:44 -0700569 data.setValue(base + ".since", getSince());
The Android Open Source Project88b60792009-03-03 19:28:42 -0800570 ParamTagInfo.makeHDF(data, base + ".paramTags", paramTags());
571 AttrTagInfo.makeReferenceHDF(data, base + ".attrRefs", comment().attrTags());
572 ThrowsTagInfo.makeHDF(data, base + ".throws", throwsTags());
573 ParameterInfo.makeHDF(data, base + ".params", parameters(), isVarArgs(), typeVariables());
574 if (isProtected()) {
575 data.setValue(base + ".scope", "protected");
576 }
577 else if (isPublic()) {
578 data.setValue(base + ".scope", "public");
579 }
580 TagInfo.makeHDF(data, base + ".returns", returnTags());
581
582 if (mTypeParameters != null) {
583 TypeInfo.makeHDF(data, base + ".generic.typeArguments", mTypeParameters, false);
584 }
585 }
586
587 public HashSet<String> typeVariables()
588 {
589 HashSet<String> result = TypeInfo.typeVariables(mTypeParameters);
590 ClassInfo cl = containingClass();
591 while (cl != null) {
592 TypeInfo[] types = cl.asTypeInfo().typeArguments();
593 if (types != null) {
594 TypeInfo.typeVariables(types, result);
595 }
596 cl = cl.containingClass();
597 }
598 return result;
599 }
600
Xavier Ducrohet5ee390d2009-09-10 13:08:27 -0700601 @Override
The Android Open Source Project88b60792009-03-03 19:28:42 -0800602 public boolean isExecutable()
603 {
604 return true;
605 }
606
607 public ClassInfo[] thrownExceptions()
608 {
609 return mThrownExceptions;
610 }
611
612 public String typeArgumentsName(HashSet<String> typeVars)
613 {
614 if (mTypeParameters == null || mTypeParameters.length == 0) {
615 return "";
616 } else {
617 return TypeInfo.typeArgumentsName(mTypeParameters, typeVars);
618 }
619 }
620
621 public boolean isAnnotationElement()
622 {
623 return mIsAnnotationElement;
624 }
625
626 public AnnotationValueInfo defaultAnnotationElementValue()
627 {
628 return mDefaultAnnotationElementValue;
629 }
Xavier Ducrohet5ee390d2009-09-10 13:08:27 -0700630
The Android Open Source Project88b60792009-03-03 19:28:42 -0800631 public void setVarargs(boolean set){
632 mIsVarargs = set;
633 }
634 public boolean isVarArgs(){
635 return mIsVarargs;
636 }
Xavier Ducrohet5ee390d2009-09-10 13:08:27 -0700637
638 @Override
The Android Open Source Project88b60792009-03-03 19:28:42 -0800639 public String toString(){
640 return this.name();
641 }
Xavier Ducrohet5ee390d2009-09-10 13:08:27 -0700642
The Android Open Source Project88b60792009-03-03 19:28:42 -0800643 public void setReason(String reason) {
644 mReasonOpened = reason;
645 }
Xavier Ducrohet5ee390d2009-09-10 13:08:27 -0700646
The Android Open Source Project88b60792009-03-03 19:28:42 -0800647 public String getReason() {
648 return mReasonOpened;
649 }
650
651 private String mFlatSignature;
652 private MethodInfo mOverriddenMethod;
653 private TypeInfo mReturnType;
654 private boolean mIsAnnotationElement;
655 private boolean mIsAbstract;
656 private boolean mIsSynchronized;
657 private boolean mIsNative;
658 private boolean mIsVarargs;
659 private boolean mDeprecatedKnown;
660 private boolean mIsDeprecated;
661 private ParameterInfo[] mParameters;
662 private ClassInfo[] mThrownExceptions;
663 private String[] mParamStrings;
664 ThrowsTagInfo[] mThrowsTags;
665 private ParamTagInfo[] mParamTags;
666 private TypeInfo[] mTypeParameters;
667 private AnnotationValueInfo mDefaultAnnotationElementValue;
668 private String mReasonOpened;
669}
670