blob: f9ebe77545ca8edd3f991be80e22f85ba8c768aa [file] [log] [blame]
The Android Open Source Projectf8057102009-03-15 16:47:16 -07001/*
2 * Copyright (C) 2009 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
17package signature.converter.doclet;
18
19import java.util.EnumSet;
20import java.util.HashMap;
21import java.util.HashSet;
22import java.util.LinkedList;
23import java.util.List;
24import java.util.Map;
25import java.util.Set;
26import java.util.Stack;
27import java.util.Map.Entry;
28
29import signature.converter.Visibility;
30import signature.model.IAnnotation;
31import signature.model.IAnnotationElement;
32import signature.model.IAnnotationField;
33import signature.model.IApi;
34import signature.model.IClassDefinition;
35import signature.model.IClassReference;
36import signature.model.IConstructor;
37import signature.model.IEnumConstant;
38import signature.model.IField;
39import signature.model.IGenericDeclaration;
40import signature.model.IMethod;
41import signature.model.IPackage;
42import signature.model.IParameter;
43import signature.model.ITypeReference;
44import signature.model.ITypeVariableDefinition;
45import signature.model.ITypeVariableReference;
46import signature.model.Kind;
47import signature.model.Modifier;
48import signature.model.impl.SigAnnotation;
49import signature.model.impl.SigAnnotationElement;
50import signature.model.impl.SigAnnotationField;
51import signature.model.impl.SigApi;
52import signature.model.impl.SigClassDefinition;
53import signature.model.impl.SigClassReference;
54import signature.model.impl.SigConstructor;
55import signature.model.impl.SigEnumConstant;
56import signature.model.impl.SigExecutableMember;
57import signature.model.impl.SigField;
58import signature.model.impl.SigMethod;
59import signature.model.impl.SigPackage;
60import signature.model.impl.SigParameter;
61import signature.model.impl.SigPrimitiveType;
62import signature.model.impl.SigTypeVariableDefinition;
63import signature.model.impl.SigTypeVariableReference;
64import signature.model.util.TypePool;
65
66import com.sun.javadoc.AnnotationDesc;
67import com.sun.javadoc.AnnotationTypeDoc;
68import com.sun.javadoc.AnnotationTypeElementDoc;
69import com.sun.javadoc.AnnotationValue;
70import com.sun.javadoc.ClassDoc;
71import com.sun.javadoc.ConstructorDoc;
72import com.sun.javadoc.ExecutableMemberDoc;
73import com.sun.javadoc.FieldDoc;
74import com.sun.javadoc.MethodDoc;
75import com.sun.javadoc.PackageDoc;
76import com.sun.javadoc.Parameter;
77import com.sun.javadoc.ParameterizedType;
78import com.sun.javadoc.ProgramElementDoc;
79import com.sun.javadoc.RootDoc;
80import com.sun.javadoc.Type;
81import com.sun.javadoc.TypeVariable;
82import com.sun.javadoc.WildcardType;
83import com.sun.javadoc.AnnotationDesc.ElementValuePair;
84
85public class DocletToSigConverter {
86
87 TypePool pool;
88 Set<String> packageNames;
89
90 /**
91 * Converts the signature information javadoc knows about into a
92 * signature.model.ISources structure.
93 */
94 public IApi convertDocletRoot(String name, RootDoc root,
95 Visibility visibility, Set<String> packageNames) {
96 this.pool = new TypePool();
97 this.packageNames = packageNames;
98
99 Set<IPackage> packages = new HashSet<IPackage>();
100
101 for (PackageDoc pack : root.specifiedPackages()) {
102 assert packageNames.contains(pack.name());
103 packages.add(convertPackage(pack));
104 }
105
106 SigApi sources = new SigApi(name, visibility);
107 sources.setPackages(packages);
108 return sources;
109 }
110
111 private IPackage convertPackage(PackageDoc packageDoc) {
112 Set<IClassDefinition> classes = new HashSet<IClassDefinition>();
113 for (ClassDoc clazz : packageDoc.allClasses()) {
114 // classes.add((IClass)convertType(clazz));
115 classes.add(convertClass(clazz));
116 }
117
118 SigPackage p = new SigPackage(packageDoc.name());
119 p.setClasses(classes);
120 p.setAnnotations(convertAnnotations(packageDoc.annotations()));
121 return p;
122 }
123
124 private SigClassDefinition convertClass(ClassDoc classDoc) {
125
126 SigClassDefinition c = pool.getClass(classDoc.containingPackage()
127 .name(), classDoc.name());
128 if (c.getKind() != Kind.UNINITIALIZED) return c;
129
130 if (classDoc.isEnum())
131 c.setKind(Kind.ENUM);
132 else if (classDoc.isInterface())
133 c.setKind(Kind.INTERFACE);
134 else if (classDoc.isClass())
135 c.setKind(Kind.CLASS);
136 else if (classDoc.isAnnotationType()) c.setKind(Kind.ANNOTATION);
137
138 if (!packageNames.contains(c.getPackageName())) {
139 // no additional conversion for this class is necessary
140 initializeClass(c);
141 return c;
142 }
143
144 c.setModifiers(convertModifiers(classDoc.modifierSpecifier()));
145 if (Kind.INTERFACE.equals(c.getKind())
146 || Kind.ANNOTATION.equals(c.getKind())) {
147 c.getModifiers().add(Modifier.ABSTRACT);
148 }
149
150 // superclass may be a class or a parameterized type (e.g. extends
151 // List<String>),
152 // may also be null if classDoc is an interface
153 Type superclassType = classDoc.superclassType();
154 if (superclassType != null) {
155 c.setSuperClass(convertTypeReference(classDoc.superclassType()));
156 } else {
157 c.setSuperClass(null);
158 }
159
160 Set<ITypeReference> interfaces = new HashSet<ITypeReference>();
161 for (Type interfaceType : classDoc.interfaceTypes()) {
162 interfaces.add(convertTypeReference(interfaceType));
163 }
164 c.setInterfaces(interfaces);
165
166 ClassDoc containingClass = classDoc.containingClass();
167 if (containingClass != null)
168 c.setDeclaringClass(convertClass(containingClass));
169 else
170 c.setDeclaringClass(null);
171
172 Set<IClassDefinition> innerClasses = new HashSet<IClassDefinition>();
173 for (ClassDoc innerClass : classDoc.innerClasses()) {
174 innerClasses.add(convertClass(innerClass));
175 }
176 c.setInnerClasses(innerClasses);
177
178 Set<IConstructor> constructors = new HashSet<IConstructor>();
179 for (ConstructorDoc constructor : classDoc.constructors()) {
180 constructors.add(convertConstructor(constructor));
181 }
182 c.setConstructors(constructors);
183
184 Set<IMethod> methods = new HashSet<IMethod>();
185 for (MethodDoc method : classDoc.methods()) {
186 methods.add(convertMethod(method));
187 }
188 c.setMethods(methods);
189
190 Set<IField> fields = new HashSet<IField>();
191 for (FieldDoc field : classDoc.fields()) {
192 fields.add(convertField(field));
193 }
194 c.setFields(fields);
195
196 Set<IEnumConstant> enumConstants = new HashSet<IEnumConstant>();
197 int ordinal = 0;
198 for (FieldDoc enumConstant : classDoc.enumConstants()) {
199 enumConstants.add(convertEnumConstant(enumConstant, ordinal++));
200 }
201 c.setEnumConstants(enumConstants);
202
203 List<ITypeVariableDefinition> typeParameters =
204 new LinkedList<ITypeVariableDefinition>();
205 for (TypeVariable typeVariable : classDoc.typeParameters()) {
206 typeParameters
207 .add(((ITypeVariableReference) convertTypeReference(
208 typeVariable)).getTypeVariableDefinition());
209 }
210 c.setTypeParameters(typeParameters);
211
212 if (classDoc.isAnnotationType()) {
213 Map<SigAnnotationField, AnnotationTypeElementDoc> annotationFieldAnnotations =
214 new HashMap<SigAnnotationField, AnnotationTypeElementDoc>();
215
216 // AnnotationTypeDoc annotationType =
217 // classDoc.asAnnotationTypeDoc(); // bug in Doclet Implementation,
218 // has been reported to sun
219 AnnotationTypeDoc annotationType = (AnnotationTypeDoc) classDoc;
220
221 Set<IAnnotationField> annotationFields =
222 new HashSet<IAnnotationField>();
223 for (AnnotationTypeElementDoc annotationElement : annotationType
224 .elements()) {
225 SigAnnotationField annotationField = new SigAnnotationField(
226 annotationElement.name());
227 annotationField.setModifiers(convertModifiers(annotationElement
228 .modifierSpecifier()));
229 annotationField.setType(convertTypeReference(annotationElement
230 .returnType()));
231 annotationField
232 .setDefaultValue(convertAnnotationValue(
233 annotationElement.defaultValue()));
234
235 // the annotations on fields are set later because these
236 // annotations may be of
237 // the same type and may use fields which are not yet defined
238 annotationFieldAnnotations.put(annotationField,
239 annotationElement);
240
241 annotationFields.add(annotationField);
242 }
243 c.setAnnotationFields(annotationFields);
244
245 // set annotation field annotations
246 for (Entry<SigAnnotationField, AnnotationTypeElementDoc> entry :
247 annotationFieldAnnotations.entrySet()) {
248 entry.getKey().setAnnotations(
249 convertAnnotations(entry.getValue().annotations()));
250 }
251 } else { // no annotation type
252 c.setAnnotationFields(null);
253 }
254
255 // set class annotations
256 c.setAnnotations(convertAnnotations(classDoc.annotations()));
257
258 return c;
259
260 }
261
262 private Object convertAnnotationValue(AnnotationValue annotationValue) {
263 if (annotationValue == null) {
264 return null;
265 }
266 Object value = annotationValue.value();
267 if (value instanceof Type) {
268 // Type contains primitive types as well, e.g. void.class
269 return convertTypeReference((Type) value);
270 } else if (value instanceof String) {
271 return value;
272 } else if (value instanceof Double || value instanceof Float
273 || value instanceof Long || value instanceof Integer
274 || value instanceof Short || value instanceof Byte
275 || value instanceof Character || value instanceof Boolean) {
276 return value;
277 } else if (value instanceof FieldDoc) {
278 FieldDoc field = (FieldDoc) value;
279 String name = field.name();
280 ITypeReference fieldType = convertTypeReference(field.type());
281 IClassReference fieldClassRef = (IClassReference) fieldType;
282 IClassDefinition fieldClass = fieldClassRef.getClassDefinition();
283
284 assert fieldClass.getKind() == Kind.ENUM;
285 Set<IEnumConstant> constants = fieldClass.getEnumConstants();
286 for (IEnumConstant enumConstant : constants) {
287 if (enumConstant.getName().equals(name)) value = enumConstant;
288 }
289 assert value instanceof IEnumConstant;
290 return value;
291 } else if (value instanceof AnnotationDesc) {
292 return convertAnnotation((AnnotationDesc) value);
293 } else if (value instanceof AnnotationValue) {
294 return convertAnnotationValue((AnnotationValue) value);
295 } else if (value instanceof AnnotationValue[]) {
296 AnnotationValue[] arr = (AnnotationValue[]) value;
297 int length = arr.length;
298 Object[] annotationArray = new Object[length];
299 for (int i = 0; i < length; i++) {
300 annotationArray[i] = convertAnnotationValue(arr[i]);
301 }
302 return annotationArray;
303 } else {
304 throw new RuntimeException("not expected case");
305 }
306 }
307
308 private ITypeReference convertArrayType(Type type) {
309 assert type.asWildcardType() == null;
310 assert type.asAnnotationTypeDoc() == null;
311
312 ITypeReference baseType = null;
313 if (type.asTypeVariable() != null) {
314 baseType = convertTypeReference(type.asTypeVariable());
315 } else if (type.asParameterizedType() != null) {
316 baseType = convertTypeReference(type.asParameterizedType());
317 } else if (type.asClassDoc() != null) {
318 baseType = new SigClassReference(convertClass(type.asClassDoc()));
319 } else if (type.isPrimitive()) {
320 baseType = SigPrimitiveType.valueOfTypeName(type.typeName());
321 } else {
322 throw new RuntimeException(type.toString());
323 }
324
325 ITypeReference arrayType = baseType;
326 int dimension = type.dimension().length() / 2;
327 while (dimension > 0) {
328 arrayType = pool.getArrayType(arrayType);
329 dimension--;
330 }
331
332 return arrayType;
333 }
334
335 private SigTypeVariableDefinition currentTypeVariableDefinition = null;
336
337 private ITypeReference convertTypeReference(Type type) {
338 assert type != null;
339
340 if (!"".equals(type.dimension())) {
341 return convertArrayType(type);
342 }
343
344 ParameterizedType pType = type.asParameterizedType();
345 if (pType != null) {
346 ITypeReference ownerType = null;
347 Type containingType = pType.containingType();
348 if (containingType != null)
349 ownerType = convertTypeReference(containingType);
350 IClassReference rawType = new SigClassReference(convertClass(pType
351 .asClassDoc()));
352
353 List<ITypeReference> typeArguments =
354 new LinkedList<ITypeReference>();
355 for (Type typeArgument : pType.typeArguments()) {
356 typeArguments.add(convertTypeReference(typeArgument));
357 }
358
359 if (typeArguments.size() > 0) {
360 return pool.getParameterizedType(ownerType, rawType,
361 typeArguments);
362 } else {
363 return rawType;
364 }
365 }
366
367 TypeVariable tv = type.asTypeVariable();
368 if (tv != null) {
369 String name = tv.typeName();
370
371 if (currentTypeVariableDefinition != null
372 && name.equals(currentTypeVariableDefinition.getName()))
373 return new SigTypeVariableReference(
374 currentTypeVariableDefinition);
375
376 IGenericDeclaration genericDeclaration = null;
377 ProgramElementDoc programElement = tv.owner();
378 if (programElement instanceof ClassDoc) {
379 genericDeclaration = convertClass((ClassDoc) programElement);
380 } else if (programElement instanceof MethodDoc
381 && currentMethod.size() > 0) {
382 genericDeclaration = currentMethod.peek();
383 } else if (programElement instanceof ConstructorDoc
384 && currentConstructor.size() > 0) {
385 genericDeclaration = currentConstructor.peek();
386 } else {
387 throw new IllegalStateException("situation not expected");
388 }
389 SigTypeVariableDefinition typeVariable = pool.getTypeVariable(name,
390 genericDeclaration);
391
392 List<ITypeReference> upperBounds = new LinkedList<ITypeReference>();
393 for (Type upperBound : tv.bounds()) {
394 // we are converting a type variable declaration which is stored
395 // in the
396 // field currentTypeVariableDefinition
397 assert currentTypeVariableDefinition == null;
398 currentTypeVariableDefinition = typeVariable;
399 upperBounds.add(convertTypeReference(upperBound));
400 currentTypeVariableDefinition = null;
401 }
402 if (upperBounds.size() == 0) {
403 // no explicit bounds, use java.lang.Object
404 upperBounds.add(pool.getClassReference("java.lang", "Object"));
405 }
406 typeVariable.setUpperBounds(upperBounds);
407
408 return new SigTypeVariableReference(typeVariable);
409 }
410
411 WildcardType wt = type.asWildcardType();
412 if (wt != null) {
413 ITypeReference lowerBound = null;
414 for (Type superBound : wt.superBounds()) {
415 lowerBound = convertTypeReference(superBound);
416 }
417
418 List<ITypeReference> upperBounds = new LinkedList<ITypeReference>();
419 for (Type upperBound : wt.extendsBounds()) {
420 upperBounds.add(convertTypeReference(upperBound));
421 }
422 if (upperBounds.size() == 0) {
423 // no explicit bounds, use java.lang.Object
424 upperBounds.add(pool.getClassReference("java.lang", "Object"));
425 }
426
427 return pool.getWildcardType(lowerBound, upperBounds);
428 }
429
430 ClassDoc c = type.asClassDoc();
431 if (c != null) {
432 return new SigClassReference(convertClass(c));
433 }
434
435 if (type.isPrimitive()) {
436 return SigPrimitiveType.valueOfTypeName(type.typeName());
437 }
438
439 throw new IllegalStateException(type.toString());
440 }
441
442 private void convertExecutableMember(ExecutableMemberDoc member,
443 SigExecutableMember m) {
444 Set<Modifier> modifiers = convertModifiers(member.modifierSpecifier());
445
446 // Doclet Bug: final values method is not considered as final
447 if (member.containingClass().isEnum() && member.name().equals("values")
448 && member.parameters().length == 0) {
449 modifiers.add(Modifier.FINAL);
450 }
451
452 if (member.containingClass().isInterface()) {
453 modifiers.add(Modifier.ABSTRACT);
454 }
455
456 m.setModifiers(modifiers);
457 m.setAnnotations(convertAnnotations(member.annotations()));
458 m.setDeclaringClass(convertClass(member.containingClass()));
459
460 List<ITypeVariableDefinition> typeParameters =
461 new LinkedList<ITypeVariableDefinition>();
462 for (TypeVariable typeParameter : member.typeParameters()) {
463 String name = typeParameter.typeName();
464 IGenericDeclaration genericDeclaration = null;
465 if (currentMethod.size() > 0)
466 genericDeclaration = currentMethod.peek();
467 else if (currentConstructor.size() > 0)
468 genericDeclaration = currentConstructor.peek();
469 else
470 throw new RuntimeException();
471 SigTypeVariableDefinition p = pool.getTypeVariable(name,
472 genericDeclaration);
473
474 List<ITypeReference> upperBounds = new LinkedList<ITypeReference>();
475 for (Type u : typeParameter.bounds()) {
476 upperBounds.add(convertTypeReference(u));
477 }
478 p.setUpperBounds(upperBounds);
479 typeParameters.add(p);
480 }
481 m.setTypeParameters(typeParameters);
482
483 List<IParameter> parameters = new LinkedList<IParameter>();
484 for (Parameter parameter : member.parameters()) {
485 SigParameter p = new SigParameter(convertTypeReference(parameter
486 .type()));
487 p.setAnnotations(convertAnnotations(parameter.annotations()));
488 parameters.add(p);
489 }
490 m.setParameters(parameters);
491
492 Set<ITypeReference> exceptions = new HashSet<ITypeReference>();
493 for (Type exceptionType : member.thrownExceptionTypes()) {
494 exceptions.add(convertTypeReference(exceptionType));
495 }
496 m.setExceptions(exceptions);
497 }
498
499 private Stack<SigMethod> currentMethod = new Stack<SigMethod>();
500
501 private IMethod convertMethod(MethodDoc method) {
502 SigMethod m = new SigMethod(method.name());
503 currentMethod.push(m);
504 convertExecutableMember(method, m);
505 m.setReturnType(convertTypeReference(method.returnType()));
506 currentMethod.pop();
507 return m;
508 }
509
510 private Stack<SigConstructor> currentConstructor =
511 new Stack<SigConstructor>();
512
513 private IConstructor convertConstructor(ConstructorDoc constructor) {
514 SigConstructor c = new SigConstructor(constructor.name());
515 currentConstructor.push(c);
516 convertExecutableMember(constructor, c);
517 currentConstructor.pop();
518 return c;
519 }
520
521 private IField convertField(FieldDoc field) {
522 SigField f = new SigField(field.name());
523 f.setAnnotations(convertAnnotations(field.annotations()));
524 f.setModifiers(convertModifiers(field.modifierSpecifier()));
525 f.setType(convertTypeReference(field.type()));
526 return f;
527 }
528
529 private IEnumConstant convertEnumConstant(FieldDoc enumConstant,
530 int ordinal) {
531 SigEnumConstant ec = new SigEnumConstant(enumConstant.name());
532 ec.setOrdinal(ordinal);
533 ec.setAnnotations(convertAnnotations(enumConstant.annotations()));
534 ec.setModifiers(convertModifiers(enumConstant.modifierSpecifier()));
535 ec.setType(convertTypeReference(enumConstant.type()));
536 return ec;
537 }
538
539 private Set<IAnnotation> convertAnnotations(
540 AnnotationDesc[] annotationDescs) {
541 Set<IAnnotation> annotations = new HashSet<IAnnotation>();
542 for (AnnotationDesc annotationDesc : annotationDescs) {
543 if (!annotationRetentionIsSource(annotationDesc))
544 annotations.add(convertAnnotation(annotationDesc));
545 }
546 return annotations;
547 }
548
549 private boolean annotationRetentionIsSource(AnnotationDesc annotationDesc) {
550 AnnotationTypeDoc type = annotationDesc.annotationType();
551 AnnotationDesc[] annotations = type.annotations();
552 for (AnnotationDesc d : annotations) {
553 if ("java.lang.annotation.Retention".equals(d.annotationType()
554 .qualifiedName())) {
555 for (ElementValuePair value : d.elementValues()) {
556 if ("value".equals(value.element().name())) {
557 return "java.lang.annotation.RetentionPolicy.SOURCE"
558 .equals(value.value().value().toString());
559 }
560 }
561 }
562 }
563 // default retention policy is CLASS
564 return false;
565 }
566
567 private IAnnotation convertAnnotation(AnnotationDesc annotationDesc) {
568 SigAnnotation a = new SigAnnotation();
569
570 IClassReference annotationType = (IClassReference) convertTypeReference(
571 annotationDesc.annotationType());
572 a.setType(annotationType);
573
574 Set<IAnnotationElement> elements = new HashSet<IAnnotationElement>();
575 for (AnnotationDesc.ElementValuePair pair : annotationDesc
576 .elementValues()) {
577 SigAnnotationElement element = new SigAnnotationElement();
578 elements.add(element);
579
580 element.setValue(convertAnnotationValue(pair.value()));
581 String name = pair.element().name();
582 for (IAnnotationField field : annotationType.getClassDefinition()
583 .getAnnotationFields()) {
584 if (field.getName().equals(name)) {
585 element.setDeclaringField(field);
586 }
587 }
588 }
589 a.setElements(elements);
590 return a;
591 }
592
593 private void initializeClass(SigClassDefinition c) {
594 c.setAnnotationFields(null);
595 c.setAnnotations(null);
596 c.setConstructors(null);
597 c.setDeclaringClass(null);
598 c.setEnumConstants(null);
599 c.setFields(null);
600 c.setInnerClasses(null);
601 c.setInterfaces(null);
602 c.setMethods(null);
603 c.setModifiers(null);
604 c.setSuperClass(null);
605 c.setTypeParameters(null);
606 }
607
608 private Set<Modifier> convertModifiers(int mod) {
609 Set<Modifier> modifiers = EnumSet.noneOf(Modifier.class);
610 if (java.lang.reflect.Modifier.isAbstract(mod))
611 modifiers.add(Modifier.ABSTRACT);
612 if (java.lang.reflect.Modifier.isFinal(mod))
613 modifiers.add(Modifier.FINAL);
614 // if (java.lang.reflect.Modifier.isNative(mod))
615 // modifiers.add(Modifier.NATIVE);
616 if (java.lang.reflect.Modifier.isPrivate(mod))
617 modifiers.add(Modifier.PRIVATE);
618 if (java.lang.reflect.Modifier.isProtected(mod))
619 modifiers.add(Modifier.PROTECTED);
620 if (java.lang.reflect.Modifier.isPublic(mod))
621 modifiers.add(Modifier.PUBLIC);
622 if (java.lang.reflect.Modifier.isStatic(mod))
623 modifiers.add(Modifier.STATIC);
624 // if (java.lang.reflect.Modifier.isStrict(mod))
625 // modifiers.add(Modifier.STRICT);
626 // if (java.lang.reflect.Modifier.isSynchronized(mod))
627 // modifiers.add(Modifier.SYNCHRONIZED);
628 // if (java.lang.reflect.Modifier.isTransient(mod))
629 // modifiers.add(Modifier.TRANSIENT);
630 if (java.lang.reflect.Modifier.isVolatile(mod))
631 modifiers.add(Modifier.VOLATILE);
632
633 return modifiers;
634 }
635
636}