1 /* *******************************************************************
2 * Copyright (c) 2002,2010 Contributors
4 * This program and the accompanying materials are made available
5 * under the terms of the Eclipse Public License v 2.0
6 * which accompanies this distribution and is available at
7 * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
10 * PARC initial implementation
11 * Alexandre Vasseur support for @AJ perClause
12 * ******************************************************************/
14 package org.aspectj.ajdt.internal.compiler.lookup;
16 import java.util.ArrayList;
17 import java.util.Collection;
18 import java.util.Collections;
19 import java.util.List;
21 import org.aspectj.ajdt.internal.compiler.ast.AdviceDeclaration;
22 import org.aspectj.ajdt.internal.compiler.ast.AspectDeclaration;
23 import org.aspectj.ajdt.internal.compiler.ast.DeclareAnnotationDeclaration;
24 import org.aspectj.ajdt.internal.compiler.ast.DeclareDeclaration;
25 import org.aspectj.ajdt.internal.compiler.ast.InterTypeDeclaration;
26 import org.aspectj.ajdt.internal.compiler.ast.PointcutDeclaration;
27 import org.aspectj.ajdt.internal.core.builder.EclipseSourceContext;
28 import org.aspectj.bridge.IMessage;
29 import org.aspectj.org.eclipse.jdt.core.compiler.CharOperation;
30 import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ASTNode;
31 import org.aspectj.org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
32 import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Annotation;
33 import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Argument;
34 import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ArrayInitializer;
35 import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ClassLiteralAccess;
36 import org.aspectj.org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
37 import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Expression;
38 import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Literal;
39 import org.aspectj.org.eclipse.jdt.internal.compiler.ast.MarkerAnnotation;
40 import org.aspectj.org.eclipse.jdt.internal.compiler.ast.MemberValuePair;
41 import org.aspectj.org.eclipse.jdt.internal.compiler.ast.NameReference;
42 import org.aspectj.org.eclipse.jdt.internal.compiler.ast.NormalAnnotation;
43 import org.aspectj.org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference;
44 import org.aspectj.org.eclipse.jdt.internal.compiler.ast.SingleMemberAnnotation;
45 import org.aspectj.org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
46 import org.aspectj.org.eclipse.jdt.internal.compiler.ast.StringLiteral;
47 import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
48 import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeParameter;
49 import org.aspectj.org.eclipse.jdt.internal.compiler.impl.Constant;
50 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding;
51 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ArrayBinding;
52 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding;
53 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.Binding;
54 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
55 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
56 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
57 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
58 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
59 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.SyntheticMethodBinding;
60 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TagBits;
61 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
62 import org.aspectj.weaver.AbstractReferenceTypeDelegate;
63 import org.aspectj.weaver.AnnotationAJ;
64 import org.aspectj.weaver.AnnotationAnnotationValue;
65 import org.aspectj.weaver.AnnotationNameValuePair;
66 import org.aspectj.weaver.AnnotationTargetKind;
67 import org.aspectj.weaver.AnnotationValue;
68 import org.aspectj.weaver.ArrayAnnotationValue;
69 import org.aspectj.weaver.BCException;
70 import org.aspectj.weaver.ClassAnnotationValue;
71 import org.aspectj.weaver.EnumAnnotationValue;
72 import org.aspectj.weaver.ReferenceType;
73 import org.aspectj.weaver.ResolvedMember;
74 import org.aspectj.weaver.ResolvedPointcutDefinition;
75 import org.aspectj.weaver.ResolvedType;
76 import org.aspectj.weaver.StandardAnnotation;
77 import org.aspectj.weaver.TypeVariable;
78 import org.aspectj.weaver.UnresolvedType;
79 import org.aspectj.weaver.WeaverStateInfo;
80 import org.aspectj.weaver.World;
81 import org.aspectj.weaver.bcel.AtAjAttributes.LazyResolvedPointcutDefinition;
82 import org.aspectj.weaver.patterns.Declare;
83 import org.aspectj.weaver.patterns.FormalBinding;
84 import org.aspectj.weaver.patterns.ParserException;
85 import org.aspectj.weaver.patterns.PatternParser;
86 import org.aspectj.weaver.patterns.PerClause;
87 import org.aspectj.weaver.patterns.PerFromSuper;
88 import org.aspectj.weaver.patterns.PerSingleton;
89 import org.aspectj.weaver.patterns.Pointcut;
92 * Supports viewing eclipse TypeDeclarations/SourceTypeBindings as a ResolvedType
95 * @author Andy Clement
97 public class EclipseSourceType extends AbstractReferenceTypeDelegate {
98 private static final char[] pointcutSig = "Lorg/aspectj/lang/annotation/Pointcut;".toCharArray();
99 private static final char[] aspectSig = "Lorg/aspectj/lang/annotation/Aspect;".toCharArray();
100 protected ResolvedPointcutDefinition[] declaredPointcuts = null;
101 protected ResolvedMember[] declaredMethods = null;
102 protected ResolvedMember[] declaredFields = null;
104 public List<Declare> declares = new ArrayList<>();
105 public List<EclipseTypeMunger> typeMungers = new ArrayList<>();
107 private final EclipseFactory factory;
109 private final SourceTypeBinding binding;
110 private final TypeDeclaration declaration;
111 private final CompilationUnitDeclaration unit;
112 private boolean annotationsFullyResolved = false;
113 private boolean annotationTypesAreResolved = false;
114 private ResolvedType[] annotationTypes = null;
116 private boolean discoveredAnnotationTargetKinds = false;
117 private AnnotationTargetKind[] annotationTargetKinds;
118 private AnnotationAJ[] annotations = null;
120 protected EclipseFactory eclipseWorld() {
124 public EclipseSourceType(ReferenceType resolvedTypeX, EclipseFactory factory, SourceTypeBinding binding,
125 TypeDeclaration declaration, CompilationUnitDeclaration unit) {
126 super(resolvedTypeX, true);
127 this.factory = factory;
128 this.binding = binding;
129 this.declaration = declaration;
132 setSourceContext(new EclipseSourceContext(declaration.compilationResult));
133 resolvedTypeX.setStartPos(declaration.sourceStart);
134 resolvedTypeX.setEndPos(declaration.sourceEnd);
138 public boolean isAspect() {
139 final boolean isCodeStyle = declaration instanceof AspectDeclaration;
140 return isCodeStyle ? isCodeStyle : isAnnotationStyleAspect();
144 public boolean isAnonymous() {
145 if (declaration.binding != null) {
146 return declaration.binding.isAnonymousType();
148 return ((declaration.modifiers & (ASTNode.IsAnonymousType | ASTNode.IsLocalType)) != 0);
152 public boolean isNested() {
153 if (declaration.binding != null) {
154 return (declaration.binding.isMemberType());
156 return ((declaration.modifiers & ASTNode.IsMemberType) != 0);
160 public ResolvedType getOuterClass() {
161 if (declaration.binding != null) {
162 ReferenceBinding enclosingType = declaration.binding.enclosingType();
163 return enclosingType==null?null:eclipseWorld().fromEclipse(enclosingType);
165 // TODO are we going to make a mistake here if the binding is null?
166 // Do we ever get asked when the binding is null
167 if (declaration.enclosingType == null) {
170 return eclipseWorld().fromEclipse(declaration.enclosingType.binding);
174 public boolean isAnnotationStyleAspect() {
175 if (declaration.annotations == null) {
178 ResolvedType[] annotations = getAnnotationTypes();
179 for (ResolvedType annotation : annotations) {
180 if ("org.aspectj.lang.annotation.Aspect".equals(annotation.getName())) {
187 /** Returns "" if there is a problem */
188 private String getPointcutStringFromAnnotationStylePointcut(AbstractMethodDeclaration amd) {
189 Annotation[] ans = amd.annotations;
193 for (Annotation an : ans) {
194 if (an.resolvedType == null) {
195 continue; // XXX happens if we do this very early from
197 // buildInterTypeandPerClause
198 // may prevent us from resolving references made in @Pointcuts to
199 // an @Pointcut in a code-style aspect
200 char[] sig = an.resolvedType.signature();
201 if (CharOperation.equals(pointcutSig, sig)) {
202 if (an.memberValuePairs().length == 0) {
203 return ""; // empty pointcut expression
205 Expression expr = an.memberValuePairs()[0].value;
206 if (expr instanceof StringLiteral) {
207 StringLiteral sLit = ((StringLiteral) expr);
208 return new String(sLit.source());
209 } else if (expr instanceof NameReference && (((NameReference) expr).binding instanceof FieldBinding)) {
210 Binding b = ((NameReference) expr).binding;
211 Constant c = ((FieldBinding) b).constant();
212 return c.stringValue();
214 throw new BCException("Do not know how to recover pointcut definition from " + expr + " (type "
215 + expr.getClass().getName() + ")");
222 private boolean isAnnotationStylePointcut(Annotation[] annotations) {
223 if (annotations == null) {
226 for (Annotation annotation : annotations) {
227 if (annotation.resolvedType == null) {
228 continue; // XXX happens if we do this very early from
230 // buildInterTypeandPerClause
231 // may prevent us from resolving references made in @Pointcuts to
232 // an @Pointcut in a code-style aspect
233 char[] sig = annotation.resolvedType.signature();
234 if (CharOperation.equals(pointcutSig, sig)) {
242 public WeaverStateInfo getWeaverState() {
247 public ResolvedType getSuperclass() {
248 if (binding.isInterface()) {
249 return getResolvedTypeX().getWorld().getCoreType(UnresolvedType.OBJECT);
251 // XXX what about java.lang.Object
252 return eclipseWorld().fromEclipse(binding.superclass());
256 public ResolvedType[] getDeclaredInterfaces() {
257 return eclipseWorld().fromEclipse(binding.superInterfaces());
260 protected void fillDeclaredMembers() {
261 List<ResolvedMember> declaredPointcuts = new ArrayList<>();
262 List<ResolvedMember> declaredMethods = new ArrayList<>();
263 List<ResolvedMember> declaredFields = new ArrayList<>();
265 MethodBinding[] ms = binding.methods(); // the important side-effect of this call is to make
266 // sure bindings are completed
267 AbstractMethodDeclaration[] methods = declaration.methods;
268 if (methods != null) {
269 for (AbstractMethodDeclaration amd : methods) {
270 if (amd == null || amd.ignoreFurtherInvestigation) {
273 if (amd instanceof PointcutDeclaration) {
274 PointcutDeclaration d = (PointcutDeclaration) amd;
275 ResolvedPointcutDefinition df = d.makeResolvedPointcutDefinition(factory);
277 declaredPointcuts.add(df);
279 } else if (amd instanceof InterTypeDeclaration) {
280 // these are handled in a separate pass
282 } else if (amd instanceof DeclareDeclaration && !(amd instanceof DeclareAnnotationDeclaration)) { // surfaces
286 // these are handled in a separate pass
288 } else if (amd instanceof AdviceDeclaration) {
289 // these are ignored during compilation and only used during
292 } else if ((amd.annotations != null) && isAnnotationStylePointcut(amd.annotations)) {
293 // consider pointcuts defined via annotations
294 ResolvedPointcutDefinition df = makeResolvedPointcutDefinition(amd);
296 declaredPointcuts.add(df);
299 if (amd.binding == null || !amd.binding.isValidBinding()) {
302 ResolvedMember member = factory.makeResolvedMember(amd.binding);
304 boolean positionKnown = true;
305 if (amd.binding.sourceMethod() == null) {
306 if (amd.binding.declaringClass instanceof SourceTypeBinding) {
307 SourceTypeBinding stb = ((SourceTypeBinding) amd.binding.declaringClass);
308 if (stb.scope == null || stb.scope.referenceContext == null) {
309 positionKnown = false;
313 if (positionKnown) { // pr229829
314 member.setSourceContext(new EclipseSourceContext(unit.compilationResult, amd.binding.sourceStart()));
315 member.setPosition(amd.binding.sourceStart(), amd.binding.sourceEnd());
317 member.setSourceContext(new EclipseSourceContext(unit.compilationResult, 0));
318 member.setPosition(0, 0);
321 declaredMethods.add(member);
327 // The bindings for the eclipse binding will include values/valueof
328 for (MethodBinding mb : ms) {
329 if ((mb instanceof SyntheticMethodBinding) && mb.isStatic()) { // cannot use .isSynthetic() because it isn't truly synthetic
330 if (CharOperation.equals(mb.selector, valuesCharArray) && mb.parameters.length == 0 && mb.returnType.isArrayType() && ((ArrayBinding) mb.returnType).leafComponentType() == binding) {
331 // static <EnumType>[] values()
332 ResolvedMember valuesMember = factory.makeResolvedMember(mb);
333 valuesMember.setSourceContext(new EclipseSourceContext(unit.compilationResult, 0));
334 valuesMember.setPosition(0, 0);
335 declaredMethods.add(valuesMember);
336 } else if (CharOperation.equals(mb.selector, valueOfCharArray) && mb.parameters.length == 1 && CharOperation.equals(mb.parameters[0].signature(), jlString) && mb.returnType == binding) {
337 // static <EnumType> valueOf(String)
338 ResolvedMember valueOfMember = factory.makeResolvedMember(mb);
339 valueOfMember.setSourceContext(new EclipseSourceContext(unit.compilationResult, 0));
340 valueOfMember.setPosition(0, 0);
341 declaredMethods.add(valueOfMember);
347 FieldBinding[] fields = binding.fields();
348 for (FieldBinding f : fields) {
349 declaredFields.add(factory.makeResolvedMember(f));
352 this.declaredPointcuts = declaredPointcuts.toArray(new ResolvedPointcutDefinition[0]);
353 this.declaredMethods = declaredMethods.toArray(new ResolvedMember[0]);
354 this.declaredFields = declaredFields.toArray(new ResolvedMember[0]);
357 private final static char[] valuesCharArray = "values".toCharArray();
358 private final static char[] valueOfCharArray = "valueOf".toCharArray();
359 private final static char[] jlString = "Ljava/lang/String;".toCharArray();
362 private ResolvedPointcutDefinition makeResolvedPointcutDefinition(AbstractMethodDeclaration md) {
363 if (md.binding == null) {
364 return null; // there is another error that has caused this...
368 EclipseSourceContext eSourceContext = new EclipseSourceContext(md.compilationResult);
370 if (!md.isAbstract()) {
371 String expression = getPointcutStringFromAnnotationStylePointcut(md);
373 pc = new PatternParser(expression, eSourceContext).parsePointcut();
374 } catch (ParserException pe) { // error will be reported by other
376 pc = Pointcut.makeMatchesNothing(Pointcut.SYMBOLIC);
380 FormalBinding[] bindings = buildFormalAdviceBindingsFrom(md);
382 ResolvedPointcutDefinition rpd = new LazyResolvedPointcutDefinition(factory.fromBinding(md.binding.declaringClass),
383 md.modifiers, new String(md.selector), factory.fromBindings(md.binding.parameters),
384 factory.fromBinding(md.binding.returnType), pc, new EclipseScope(bindings, md.scope));
386 rpd.setPosition(md.sourceStart, md.sourceEnd);
387 rpd.setSourceContext(eSourceContext);
391 private static final char[] joinPoint = "Lorg/aspectj/lang/JoinPoint;".toCharArray();
392 private static final char[] joinPointStaticPart = "Lorg/aspectj/lang/JoinPoint$StaticPart;".toCharArray();
393 private static final char[] joinPointEnclosingStaticPart = "Lorg/aspectj/lang/JoinPoint$EnclosingStaticPart;".toCharArray();
394 private static final char[] proceedingJoinPoint = "Lorg/aspectj/lang/ProceedingJoinPoint;".toCharArray();
396 private FormalBinding[] buildFormalAdviceBindingsFrom(AbstractMethodDeclaration mDecl) {
397 if (mDecl.arguments == null) {
398 return new FormalBinding[0];
400 if (mDecl.binding == null) {
401 return new FormalBinding[0];
403 EclipseFactory factory = EclipseFactory.fromScopeLookupEnvironment(mDecl.scope);
404 String extraArgName = "";// maybeGetExtraArgName();
405 FormalBinding[] ret = new FormalBinding[mDecl.arguments.length];
406 for (int i = 0; i < mDecl.arguments.length; i++) {
407 Argument arg = mDecl.arguments[i];
408 String name = new String(arg.name);
409 TypeBinding argTypeBinding = mDecl.binding.parameters[i];
410 UnresolvedType type = factory.fromBinding(argTypeBinding);
411 if (CharOperation.equals(joinPoint, argTypeBinding.signature())
412 || CharOperation.equals(joinPointStaticPart, argTypeBinding.signature())
413 || CharOperation.equals(joinPointEnclosingStaticPart, argTypeBinding.signature())
414 || CharOperation.equals(proceedingJoinPoint, argTypeBinding.signature()) || name.equals(extraArgName)) {
415 ret[i] = new FormalBinding.ImplicitFormalBinding(type, name, i);
417 ret[i] = new FormalBinding(type, name, i, arg.sourceStart, arg.sourceEnd);
424 * This method may not return all fields, for example it may not include the ajc$initFailureCause or ajc$perSingletonInstance
425 * fields - see bug 129613
428 public ResolvedMember[] getDeclaredFields() {
429 if (declaredFields == null) {
430 fillDeclaredMembers();
432 return declaredFields;
436 * This method may not return all methods, for example it may not include clinit, aspectOf, hasAspect or ajc$postClinit methods
440 public ResolvedMember[] getDeclaredMethods() {
441 if (declaredMethods == null) {
442 fillDeclaredMembers();
444 return declaredMethods;
448 public ResolvedMember[] getDeclaredPointcuts() {
449 if (declaredPointcuts == null) {
450 fillDeclaredMembers();
452 return declaredPointcuts;
456 public int getModifiers() {
457 // only return the real Java modifiers, not the extra eclipse ones
458 return binding.modifiers & ExtraCompilerModifiers.AccJustFlag;
462 public String toString() {
463 return "EclipseSourceType(" + new String(binding.sourceName()) + ")";
466 // XXX make sure this is applied to classes and interfaces
467 public void checkPointcutDeclarations() {
468 ResolvedMember[] pointcuts = getDeclaredPointcuts();
469 boolean sawError = false;
470 for (int i = 0, len = pointcuts.length; i < len; i++) {
471 if (pointcuts[i] == null) {
472 // Something else is broken in this file and will be reported separately
475 if (pointcuts[i].isAbstract()) {
476 if (!this.isAspect()) {
477 eclipseWorld().showMessage(IMessage.ERROR, "The abstract pointcut " + pointcuts[i].getName()+ " can only be defined in an aspect",
478 pointcuts[i].getSourceLocation(), null);
480 } else if (!binding.isAbstract()) {
481 eclipseWorld().showMessage(IMessage.ERROR, "abstract pointcut in concrete aspect: " + pointcuts[i],
482 pointcuts[i].getSourceLocation(), null);
487 for (int j = i + 1; j < len; j++) {
488 if (pointcuts[j] == null) {
489 // Something else is broken in this file and will be reported separately
492 if (pointcuts[i].getName().equals(pointcuts[j].getName())) {
493 eclipseWorld().showMessage(IMessage.ERROR, "duplicate pointcut name: " + pointcuts[j].getName(),
494 pointcuts[i].getSourceLocation(), pointcuts[j].getSourceLocation());
500 // now check all inherited pointcuts to be sure that they're handled
502 if (sawError || !isAspect()) {
506 // find all pointcuts that override ones from super and check override
508 // i.e. same signatures and greater or equal visibility
509 // find all inherited abstract pointcuts and make sure they're
510 // concretized if I'm concrete
511 // find all inherited pointcuts and make sure they don't conflict
512 getResolvedTypeX().getExposedPointcuts(); // ??? this is an odd
518 // public CrosscuttingMembers collectCrosscuttingMembers() {
519 // return crosscuttingMembers;
522 // public ISourceLocation getSourceLocation() {
523 // TypeDeclaration dec = binding.scope.referenceContext;
524 // return new EclipseSourceLocation(dec.compilationResult, dec.sourceStart,
529 public boolean isInterface() {
530 return binding.isInterface();
533 // XXXAJ5: Should be constants in the eclipse compiler somewhere, once it
535 public final static short ACC_ANNOTATION = 0x2000;
536 public final static short ACC_ENUM = 0x4000;
539 public boolean isEnum() {
540 return (binding.getAccessFlags() & ACC_ENUM) != 0;
544 public boolean isAnnotation() {
545 return (binding.getAccessFlags() & ACC_ANNOTATION) != 0;
549 public boolean isAnnotationWithRuntimeRetention() {
550 if (!isAnnotation()) {
553 return (binding.getAnnotationTagBits() & TagBits.AnnotationRetentionMASK) == TagBits.AnnotationRuntimeRetention;
558 public String getRetentionPolicy() {
559 if (isAnnotation()) {
560 if ((binding.getAnnotationTagBits() & TagBits.AnnotationRetentionMASK) == TagBits.AnnotationRuntimeRetention) {
563 if ((binding.getAnnotationTagBits() & TagBits.AnnotationRetentionMASK) == TagBits.AnnotationSourceRetention) {
566 if ((binding.getAnnotationTagBits() & TagBits.AnnotationRetentionMASK) == TagBits.AnnotationClassRetention) {
574 public boolean canAnnotationTargetType() {
575 if (isAnnotation()) {
576 return ((binding.getAnnotationTagBits() & TagBits.AnnotationForType) != 0);
582 public AnnotationTargetKind[] getAnnotationTargetKinds() {
583 if (discoveredAnnotationTargetKinds) {
584 return annotationTargetKinds;
586 discoveredAnnotationTargetKinds = true;
587 annotationTargetKinds = null; // null means we have no idea or the
588 // @Target annotation hasn't been used
589 // if (isAnnotation()) {
590 // Annotation[] annotationsOnThisType = declaration.annotations;
591 // if (annotationsOnThisType != null) {
592 // for (int i = 0; i < annotationsOnThisType.length; i++) {
593 // Annotation a = annotationsOnThisType[i];
594 // if (a.resolvedType != null) {
595 // String packageName = new
596 // String(a.resolvedType.qualifiedPackageName()).concat(".");
597 // String sourceName = new String(a.resolvedType.qualifiedSourceName());
598 // if ((packageName +
599 // sourceName).equals(UnresolvedType.AT_TARGET.getName())) {
600 // MemberValuePair[] pairs = a.memberValuePairs();
601 // for (int j = 0; j < pairs.length; j++) {
602 // MemberValuePair pair = pairs[j];
603 // targetKind = pair.value.toString();
604 // return targetKind;
611 // return targetKind;
612 if (isAnnotation()) {
613 List<AnnotationTargetKind> targetKinds = new ArrayList<>();
615 if ((binding.getAnnotationTagBits() & TagBits.AnnotationForAnnotationType) != 0) {
616 targetKinds.add(AnnotationTargetKind.ANNOTATION_TYPE);
618 if ((binding.getAnnotationTagBits() & TagBits.AnnotationForConstructor) != 0) {
619 targetKinds.add(AnnotationTargetKind.CONSTRUCTOR);
621 if ((binding.getAnnotationTagBits() & TagBits.AnnotationForField) != 0) {
622 targetKinds.add(AnnotationTargetKind.FIELD);
624 if ((binding.getAnnotationTagBits() & TagBits.AnnotationForLocalVariable) != 0) {
625 targetKinds.add(AnnotationTargetKind.LOCAL_VARIABLE);
627 if ((binding.getAnnotationTagBits() & TagBits.AnnotationForMethod) != 0) {
628 targetKinds.add(AnnotationTargetKind.METHOD);
630 if ((binding.getAnnotationTagBits() & TagBits.AnnotationForPackage) != 0) {
631 targetKinds.add(AnnotationTargetKind.PACKAGE);
633 if ((binding.getAnnotationTagBits() & TagBits.AnnotationForParameter) != 0) {
634 targetKinds.add(AnnotationTargetKind.PARAMETER);
636 if ((binding.getAnnotationTagBits() & TagBits.AnnotationForType) != 0) {
637 targetKinds.add(AnnotationTargetKind.TYPE);
640 if (!targetKinds.isEmpty()) {
641 annotationTargetKinds = new AnnotationTargetKind[targetKinds.size()];
642 return targetKinds.toArray(annotationTargetKinds);
645 return annotationTargetKinds;
649 * Ensure the annotation types have been resolved, where resolved means the eclipse type bindings have been converted to their
650 * ResolvedType representations. This does not deeply resolve the annotations, it only does the type names.
652 private void ensureAnnotationTypesResolved() {
653 // may need to re-resolve if new annotations have been added
654 int declarationAnnoCount = (declaration.annotations == null ? 0 : declaration.annotations.length);
655 if (!annotationTypesAreResolved || declarationAnnoCount != annotationTypes.length) {
656 Annotation[] as = declaration.annotations;
658 annotationTypes = ResolvedType.NONE;
660 annotationTypes = new ResolvedType[as.length];
661 for (int a = 0; a < as.length; a++) {
662 TypeBinding tb = as[a].type.resolveType(declaration.staticInitializerScope);
664 annotationTypes[a] = ResolvedType.MISSING;
666 annotationTypes[a] = factory.fromTypeBindingToRTX(tb);
670 annotationTypesAreResolved = true;
675 public boolean hasAnnotation(UnresolvedType ofType) {
676 ensureAnnotationTypesResolved();
677 for (ResolvedType annotationType : annotationTypes) {
678 if (ofType.equals(annotationType)) {
686 * WARNING: This method does not have a complete implementation.
688 * The aim is that it converts Eclipse annotation objects to the AspectJ form of annotations (the type AnnotationAJ). The
689 * AnnotationX objects returned are wrappers over either a Bcel annotation type or the AspectJ AnnotationAJ type. The minimal
690 * implementation provided here is for processing the RetentionPolicy and Target annotation types - these are the only ones
691 * which the weaver will attempt to process from an EclipseSourceType.
693 * More notes: The pipeline has required us to implement this. With the pipeline we can be weaving a type and asking questions
694 * of annotations before they have been turned into Bcel objects - ie. when they are still in EclipseSourceType form. Without
695 * the pipeline we would have converted everything to Bcel objects before proceeding with weaving. Because the pipeline won't
696 * start weaving until all aspects have been compiled and the fact that no AspectJ constructs match on the values within
697 * annotations, this code only needs to deal with converting system annotations that the weaver needs to process
698 * (RetentionPolicy, Target).
701 public AnnotationAJ[] getAnnotations() {
702 int declarationAnnoCount = (declaration.annotations == null ? 0 : declaration.annotations.length);
703 if (annotations != null && annotations.length == declarationAnnoCount) {
704 return annotations; // only do this once
706 if (!annotationsFullyResolved || annotations.length!=declarationAnnoCount) {
707 TypeDeclaration.resolveAnnotations(declaration.staticInitializerScope, declaration.annotations, binding);
708 annotationsFullyResolved = true;
710 Annotation[] as = declaration.annotations;
711 if (as == null || as.length == 0) {
712 annotations = AnnotationAJ.EMPTY_ARRAY;
714 annotations = new AnnotationAJ[as.length];
715 for (int i = 0; i < as.length; i++) {
716 annotations[i] = convertEclipseAnnotation(as[i], factory.getWorld());
723 public boolean hasAnnotations() {
724 return (declaration.annotations != null && declaration.annotations.length != 0);
728 * Convert one eclipse annotation into an AnnotationX object containing an AnnotationAJ object.
730 * This code and the helper methods used by it will go *BANG* if they encounter anything not currently supported - this is safer
731 * than limping along with a malformed annotation. When the *BANG* is encountered the bug reporter should indicate the kind of
732 * annotation they were working with and this code can be enhanced to support it.
734 public AnnotationAJ convertEclipseAnnotation(Annotation eclipseAnnotation, World w) {
735 // TODO if it is sourcevisible, we shouldn't let it through!!!!!!!!!
737 ResolvedType annotationType = factory.fromTypeBindingToRTX(eclipseAnnotation.type.resolvedType);
738 // long bs = (eclipseAnnotation.bits & TagBits.AnnotationRetentionMASK);
739 boolean isRuntimeVisible = (eclipseAnnotation.bits & TagBits.AnnotationRetentionMASK) == TagBits.AnnotationRuntimeRetention;
740 StandardAnnotation annotationAJ = new StandardAnnotation(annotationType, isRuntimeVisible);
741 generateAnnotation(eclipseAnnotation, annotationAJ, w);
745 static class MissingImplementationException extends RuntimeException {
746 MissingImplementationException(String reason) {
752 * Use the information in the supplied eclipse based annotation to fill in the standard annotation.
754 * @param annotation eclipse based annotation representation
755 * @param annotationAJ AspectJ based annotation representation
757 private void generateAnnotation(Annotation annotation, StandardAnnotation annotationAJ, World w) {
758 if (annotation instanceof NormalAnnotation) {
759 NormalAnnotation normalAnnotation = (NormalAnnotation) annotation;
760 MemberValuePair[] memberValuePairs = normalAnnotation.memberValuePairs;
761 if (memberValuePairs != null) {
762 int memberValuePairsLength = memberValuePairs.length;
763 for (MemberValuePair memberValuePair : memberValuePairs) {
764 MethodBinding methodBinding = memberValuePair.binding;
765 if (methodBinding == null) {
766 // is this just a marker annotation?
767 if (memberValuePair.value instanceof MarkerAnnotation) {
768 MarkerAnnotation eMarkerAnnotation = (MarkerAnnotation) memberValuePair.value;
769 AnnotationBinding eMarkerAnnotationBinding = eMarkerAnnotation.getCompilerAnnotation();
770 ReferenceBinding eAnnotationType = eMarkerAnnotationBinding.getAnnotationType();
771 ResolvedType ajAnnotationType = factory.fromTypeBindingToRTX(eAnnotationType);
772 boolean isRuntimeVisible = (eMarkerAnnotation.bits & TagBits.AnnotationRetentionMASK) == TagBits.AnnotationRuntimeRetention;
773 StandardAnnotation ajAnnotation = new StandardAnnotation(ajAnnotationType, isRuntimeVisible);
774 AnnotationValue av = new AnnotationAnnotationValue(ajAnnotation);
775 AnnotationNameValuePair anvp = new AnnotationNameValuePair(new String(memberValuePair.name), av);
776 annotationAJ.addNameValuePair(anvp);
777 // } else if (memberValuePair.value instanceof NormalAnnotation) {
778 // NormalAnnotation eNormalAnnotation = (NormalAnnotation) memberValuePair.value;
779 // AnnotationBinding eMarkerAnnotationBinding = eNormalAnnotation.getCompilerAnnotation();
780 // ReferenceBinding eAnnotationType = eMarkerAnnotationBinding.getAnnotationType();
781 // ResolvedType ajAnnotationType = factory.fromTypeBindingToRTX(eAnnotationType);
782 // boolean isRuntimeVisible = (eNormalAnnotation.bits & TagBits.AnnotationRetentionMASK) ==
783 // TagBits.AnnotationRuntimeRetention;
784 // StandardAnnotation ajAnnotation = new StandardAnnotation(ajAnnotationType, isRuntimeVisible);
785 // MemberValuePair[] pairs = eNormalAnnotation.memberValuePairs;
786 // if (pairs != null) {
787 // for (int p = 0; p < pairs.length; p++) {
788 // MemberValuePair pair = pairs[p];
789 // throw new IllegalStateException("nyi");
793 // AnnotationValue av = new AnnotationAnnotationValue(ajAnnotation);
794 // AnnotationNameValuePair anvp = new AnnotationNameValuePair(new String(memberValuePair.name), av);
795 // annotationAJ.addNameValuePair(anvp);
796 } else if (memberValuePair.value instanceof Literal) {
797 AnnotationValue av = generateElementValue(memberValuePair.value,
798 ((Literal) memberValuePair.value).resolvedType);
799 AnnotationNameValuePair anvp = new AnnotationNameValuePair(new String(memberValuePair.name), av);
800 annotationAJ.addNameValuePair(anvp);
801 } else if (memberValuePair.value instanceof ArrayInitializer) {
802 ArrayInitializer arrayInitializer = (ArrayInitializer) memberValuePair.value;
803 Expression[] expressions = arrayInitializer.expressions;
804 AnnotationValue[] arrayValues = new AnnotationValue[expressions.length];
805 for (int e = 0; e < expressions.length; e++) {
806 arrayValues[e] = generateElementValue(expressions[e],
807 ((ArrayBinding) arrayInitializer.resolvedType).leafComponentType);
809 AnnotationValue array = new ArrayAnnotationValue(arrayValues);
810 AnnotationNameValuePair anvp = new AnnotationNameValuePair(new String(memberValuePair.name), array);
811 annotationAJ.addNameValuePair(anvp);
813 throw new MissingImplementationException(
814 "Please raise an AspectJ bug. AspectJ does not know how to convert this annotation ["
818 AnnotationValue av = generateElementValue(memberValuePair.value, methodBinding.returnType);
819 AnnotationNameValuePair anvp = new AnnotationNameValuePair(new String(memberValuePair.name), av);
820 annotationAJ.addNameValuePair(anvp);
824 } else if (annotation instanceof SingleMemberAnnotation) {
825 // this is a single member annotation (one member value)
826 SingleMemberAnnotation singleMemberAnnotation = (SingleMemberAnnotation) annotation;
827 MemberValuePair mvp = singleMemberAnnotation.memberValuePairs()[0];
828 if (mvp.value instanceof ArrayInitializer) {
829 ArrayInitializer arrayInitializer = (ArrayInitializer) mvp.value;
830 Expression[] expressions = arrayInitializer.expressions;
831 AnnotationValue[] arrayValues = new AnnotationValue[expressions.length];
832 for (int e = 0; e < expressions.length; e++) {
833 arrayValues[e] = generateElementValue(expressions[e],
834 ((ArrayBinding) arrayInitializer.resolvedType).leafComponentType);
836 AnnotationValue array = new ArrayAnnotationValue(arrayValues);
837 AnnotationNameValuePair anvp = new AnnotationNameValuePair(new String(mvp.name), array);
838 annotationAJ.addNameValuePair(anvp);
839 } else if (mvp.value instanceof Literal) {
840 AnnotationValue av = generateElementValue(mvp.value,
841 ((Literal) mvp.value).resolvedType);
842 AnnotationNameValuePair anvp = new AnnotationNameValuePair(new String(mvp.name), av);
843 annotationAJ.addNameValuePair(anvp);
845 MethodBinding methodBinding = mvp.binding;
846 if (methodBinding == null) {
847 throw new MissingImplementationException(
848 "Please raise an AspectJ bug. AspectJ does not know how to convert this annotation [" + annotation + "]");
850 AnnotationValue av = generateElementValue(singleMemberAnnotation.memberValue, methodBinding.returnType);
851 annotationAJ.addNameValuePair(new AnnotationNameValuePair(new String(
852 singleMemberAnnotation.memberValuePairs()[0].name), av));
855 } else if (annotation instanceof MarkerAnnotation) {
858 // this is something else...
859 throw new MissingImplementationException(
860 "Please raise an AspectJ bug. AspectJ does not know how to convert this annotation [" + annotation + "]");
864 private AnnotationValue generateElementValue(Expression defaultValue, TypeBinding memberValuePairReturnType) {
865 Constant constant = defaultValue.constant;
866 TypeBinding defaultValueBinding = defaultValue.resolvedType;
867 if (defaultValueBinding == null) {
868 throw new MissingImplementationException(
869 "Please raise an AspectJ bug. AspectJ does not know how to convert this annotation value [" + defaultValue
872 if (memberValuePairReturnType.isArrayType() && !defaultValueBinding.isArrayType()) {
873 if (constant != null && constant != Constant.NotAConstant) {
874 // Testcase for this clause is MultiProjectIncrementalTests.testAnnotations_pr262154()
875 AnnotationValue av = EclipseAnnotationConvertor.generateElementValueForConstantExpression(defaultValue,
876 defaultValueBinding);
877 return new ArrayAnnotationValue(new AnnotationValue[] { av });
879 AnnotationValue av = generateElementValueForNonConstantExpression(defaultValue, defaultValueBinding);
880 return new ArrayAnnotationValue(new AnnotationValue[] { av });
883 if (constant != null && constant != Constant.NotAConstant) {
884 AnnotationValue av = EclipseAnnotationConvertor.generateElementValueForConstantExpression(defaultValue,
885 defaultValueBinding);
887 throw new MissingImplementationException(
888 "Please raise an AspectJ bug. AspectJ does not know how to convert this annotation value ["
889 + defaultValue + "]");
892 // generateElementValue(attributeOffset, defaultValue,
893 // constant, memberValuePairReturnType.leafComponentType());
895 AnnotationValue av = generateElementValueForNonConstantExpression(defaultValue, defaultValueBinding);
902 private AnnotationValue generateElementValueForNonConstantExpression(Expression defaultValue, TypeBinding defaultValueBinding) {
903 if (defaultValueBinding != null) {
904 if (defaultValueBinding.isEnum()) {
905 FieldBinding fieldBinding = null;
906 if (defaultValue instanceof QualifiedNameReference) {
907 QualifiedNameReference nameReference = (QualifiedNameReference) defaultValue;
908 fieldBinding = (FieldBinding) nameReference.binding;
909 } else if (defaultValue instanceof SingleNameReference) {
910 SingleNameReference nameReference = (SingleNameReference) defaultValue;
911 fieldBinding = (FieldBinding) nameReference.binding;
913 throw new MissingImplementationException(
914 "Please raise an AspectJ bug. AspectJ does not know how to convert this annotation value ["
915 + defaultValue + "]");
917 if (fieldBinding != null) {
918 String sig = new String(fieldBinding.type.signature());
919 AnnotationValue enumValue = new EnumAnnotationValue(sig, new String(fieldBinding.name));
922 throw new MissingImplementationException(
923 "Please raise an AspectJ bug. AspectJ does not know how to convert this annotation value [" + defaultValue
925 } else if (defaultValue instanceof ClassLiteralAccess) {
926 ClassLiteralAccess cla = (ClassLiteralAccess)defaultValue;
927 TypeBinding claTargetType = cla.targetType;
928 // ResolvedType classLiteralType = factory.fromTypeBindingToRTX(defaultValueBinding);
929 String classLiteralSig = new String(claTargetType.signature());
930 AnnotationValue classValue = new ClassAnnotationValue(classLiteralSig);
932 } else if (defaultValueBinding.isAnnotationType()) {
933 if (defaultValue instanceof MarkerAnnotation) {
934 ResolvedType ajAnnotationType = factory.fromTypeBindingToRTX(defaultValueBinding);
935 StandardAnnotation ajAnnotation = new StandardAnnotation(ajAnnotationType,
936 ajAnnotationType.isAnnotationWithRuntimeRetention());
937 AnnotationValue av = new AnnotationAnnotationValue(ajAnnotation);
939 } else if (defaultValue instanceof NormalAnnotation) {
940 NormalAnnotation normalAnnotation = (NormalAnnotation) defaultValue;
941 ResolvedType ajAnnotationType = factory.fromTypeBindingToRTX(defaultValueBinding);
942 StandardAnnotation ajAnnotation = new StandardAnnotation(ajAnnotationType,
943 ajAnnotationType.isAnnotationWithRuntimeRetention());
944 MemberValuePair[] pairs = normalAnnotation.memberValuePairs;
946 for (MemberValuePair pair : pairs) {
947 Expression valueEx = pair.value;
948 AnnotationValue pairValue = null;
949 if (valueEx instanceof Literal) {
950 pairValue = generateElementValue(valueEx, ((Literal) valueEx).resolvedType);
952 pairValue = generateElementValue(pair.value, pair.binding.returnType);
954 ajAnnotation.addNameValuePair(new AnnotationNameValuePair(new String(pair.name), pairValue));
957 AnnotationValue av = new AnnotationAnnotationValue(ajAnnotation);
960 throw new MissingImplementationException(
961 "Please raise an AspectJ bug. AspectJ does not know how to convert this annotation value ["
962 + defaultValue + "]");
964 } else if (defaultValueBinding.isArrayType()) {
966 if (defaultValue instanceof ArrayInitializer) {
967 ArrayInitializer arrayInitializer = (ArrayInitializer) defaultValue;
968 int arrayLength = arrayInitializer.expressions != null ? arrayInitializer.expressions.length : 0;
969 AnnotationValue[] values = new AnnotationValue[arrayLength];
970 for (int i = 0; i < arrayLength; i++) {
971 values[i] = generateElementValue(arrayInitializer.expressions[i], defaultValueBinding.leafComponentType());// ,
976 ArrayAnnotationValue aav = new ArrayAnnotationValue(values);
979 throw new MissingImplementationException(
980 "Please raise an AspectJ bug. AspectJ does not know how to convert this annotation value ["
981 + defaultValue + "]");
983 // } else if (defaultValue instanceof MagicLiteral) {
984 // if (defaultValue instanceof FalseLiteral) {
985 // new AnnotationValue
986 // } else if (defaultValue instanceof TrueLiteral) {
989 // throw new MissingImplementationException(
990 // "Please raise an AspectJ bug. AspectJ does not know how to convert this annotation value ["
991 // +defaultValue+"]");
995 throw new MissingImplementationException(
996 "Please raise an AspectJ bug. AspectJ does not know how to convert this annotation value [" + defaultValue
998 // if (contentsOffset + 3 >= this.contents.length) {
999 // resizeContents(3);
1001 // contents[contentsOffset++] = (byte) 'c';
1002 // if (defaultValue instanceof ClassLiteralAccess) {
1003 // ClassLiteralAccess classLiteralAccess = (ClassLiteralAccess)
1005 // final int classInfoIndex =
1006 // constantPool.literalIndex(classLiteralAccess
1007 // .targetType.signature());
1008 // contents[contentsOffset++] = (byte) (classInfoIndex >> 8);
1009 // contents[contentsOffset++] = (byte) classInfoIndex;
1011 // contentsOffset = attributeOffset;
1015 throw new MissingImplementationException(
1016 "Please raise an AspectJ bug. AspectJ does not know how to convert this annotation value [" + defaultValue
1018 // contentsOffset = attributeOffset;
1023 public ResolvedType[] getAnnotationTypes() {
1024 ensureAnnotationTypesResolved();
1025 return annotationTypes;
1029 public PerClause getPerClause() {
1030 // should probably be: ((AspectDeclaration)declaration).perClause;
1031 // but we don't need this level of detail, and working with real per
1033 // at this stage of compilation is not worth the trouble
1034 if (!isAnnotationStyleAspect()) {
1035 if (declaration instanceof AspectDeclaration) {
1036 PerClause pc = ((AspectDeclaration) declaration).perClause;
1041 return new PerSingleton();
1043 // for @Aspect, we do need the real kind though we don't need the
1045 // at least try to get the right perclause
1046 PerClause pc = null;
1047 if (declaration instanceof AspectDeclaration) {
1048 pc = ((AspectDeclaration) declaration).perClause;
1051 PerClause.Kind kind = getPerClauseForTypeDeclaration(declaration);
1052 // returning a perFromSuper is enough to get the correct kind..
1053 // (that's really a hack - AV)
1054 return new PerFromSuper(kind);
1060 PerClause.Kind getPerClauseForTypeDeclaration(TypeDeclaration typeDeclaration) {
1061 Annotation[] annotations = typeDeclaration.annotations;
1062 if (annotations == null) {
1063 // Can happen if an aspect is extending a regular class
1066 for (Annotation annotation : annotations) {
1067 if (annotation != null && annotation.resolvedType != null
1068 && CharOperation.equals(aspectSig, annotation.resolvedType.signature())) {
1069 // found @Aspect(...)
1070 if (annotation.memberValuePairs() == null || annotation.memberValuePairs().length == 0) {
1071 // it is an @Aspect or @Aspect()
1072 // needs to use PerFromSuper if declaration extends a super
1074 PerClause.Kind kind = lookupPerClauseKind(typeDeclaration.binding.superclass);
1075 // if no super aspect, we have a @Aspect() means singleton
1077 return PerClause.SINGLETON;
1081 } else if (annotation instanceof SingleMemberAnnotation) {
1082 // it is an @Aspect(...something...)
1083 SingleMemberAnnotation theAnnotation = (SingleMemberAnnotation) annotation;
1084 String clause = new String(((StringLiteral) theAnnotation.memberValue).source());// TODO
1088 return determinePerClause(typeDeclaration, clause);
1089 } else if (annotation instanceof NormalAnnotation) {
1090 // this kind if it was added by the visitor!
1091 // it is an @Aspect(...something...)
1092 NormalAnnotation theAnnotation = (NormalAnnotation) annotation;
1093 if (theAnnotation.memberValuePairs == null || theAnnotation.memberValuePairs.length < 1) {
1094 return PerClause.SINGLETON;
1096 String clause = new String(((StringLiteral) theAnnotation.memberValuePairs[0].value).source());// TODO
1100 return determinePerClause(typeDeclaration, clause);
1102 eclipseWorld().showMessage(
1104 "@Aspect annotation is expected to be SingleMemberAnnotation with 'String value()' as unique element",
1105 new EclipseSourceLocation(typeDeclaration.compilationResult, typeDeclaration.sourceStart,
1106 typeDeclaration.sourceEnd), null);
1107 return PerClause.SINGLETON;// fallback strategy just to avoid NPE
1111 return null;// no @Aspect annotation at all (not as aspect)
1114 private PerClause.Kind determinePerClause(TypeDeclaration typeDeclaration, String clause) {
1115 if (clause.startsWith("perthis(")) {
1116 return PerClause.PEROBJECT;
1117 } else if (clause.startsWith("pertarget(")) {
1118 return PerClause.PEROBJECT;
1119 } else if (clause.startsWith("percflow(")) {
1120 return PerClause.PERCFLOW;
1121 } else if (clause.startsWith("percflowbelow(")) {
1122 return PerClause.PERCFLOW;
1123 } else if (clause.startsWith("pertypewithin(")) {
1124 return PerClause.PERTYPEWITHIN;
1125 } else if (clause.startsWith("issingleton(")) {
1126 return PerClause.SINGLETON;
1128 eclipseWorld().showMessage(
1130 "cannot determine perClause '" + clause + "'",
1131 new EclipseSourceLocation(typeDeclaration.compilationResult, typeDeclaration.sourceStart,
1132 typeDeclaration.sourceEnd), null);
1133 return PerClause.SINGLETON;// fallback strategy just to avoid NPE
1137 // adapted from AspectDeclaration
1138 private PerClause.Kind lookupPerClauseKind(ReferenceBinding binding) {
1139 final PerClause.Kind kind;
1140 if (binding instanceof BinaryTypeBinding) {
1141 ResolvedType superTypeX = factory.fromEclipse(binding);
1142 PerClause perClause = superTypeX.getPerClause();
1143 // clause is null for non aspect classes since coming from BCEL
1145 if (perClause != null) {
1146 kind = superTypeX.getPerClause().getKind();
1150 } else if (binding instanceof SourceTypeBinding) {
1151 SourceTypeBinding sourceSc = (SourceTypeBinding) binding;
1152 if (sourceSc.scope.referenceContext instanceof AspectDeclaration) {
1154 kind = ((AspectDeclaration) sourceSc.scope.referenceContext).perClause.getKind();
1155 } else { // if (sourceSc.scope.referenceContext instanceof
1156 // TypeDeclaration) {
1157 // if @Aspect: perFromSuper, else if @Aspect(..) get from anno
1159 kind = getPerClauseForTypeDeclaration((sourceSc.scope.referenceContext));
1162 // XXX need to handle this too
1169 public Collection<Declare> getDeclares() {
1174 public Collection<ResolvedMember> getPrivilegedAccesses() {
1175 return Collections.emptyList();
1179 public Collection getTypeMungers() {
1184 public boolean doesNotExposeShadowMungers() {
1189 public String getDeclaredGenericSignature() {
1190 return CharOperation.charToString(binding.genericSignature());
1194 public boolean isGeneric() {
1195 return binding.isGenericType();
1199 public TypeVariable[] getTypeVariables() {
1200 if (declaration.typeParameters == null) {
1201 return new TypeVariable[0];
1203 TypeVariable[] typeVariables = new TypeVariable[declaration.typeParameters.length];
1204 for (int i = 0; i < typeVariables.length; i++) {
1205 typeVariables[i] = typeParameter2TypeVariable(declaration.typeParameters[i]);
1207 return typeVariables;
1210 private TypeVariable typeParameter2TypeVariable(TypeParameter typeParameter) {
1211 String name = new String(typeParameter.name);
1212 ReferenceBinding superclassBinding = typeParameter.binding.superclass;
1213 UnresolvedType superclass = UnresolvedType.forSignature(new String(superclassBinding.signature()));
1214 UnresolvedType[] superinterfaces = null;
1215 ReferenceBinding[] superInterfaceBindings = typeParameter.binding.superInterfaces;
1216 if (superInterfaceBindings != null) {
1217 superinterfaces = new UnresolvedType[superInterfaceBindings.length];
1218 for (int i = 0; i < superInterfaceBindings.length; i++) {
1219 superinterfaces[i] = UnresolvedType.forSignature(new String(superInterfaceBindings[i].signature()));
1222 // XXX what about lower binding?
1223 TypeVariable tv = new TypeVariable(name, superclass, superinterfaces);
1224 tv.setDeclaringElement(factory.fromBinding(typeParameter.binding.declaringElement));
1225 tv.setRank(typeParameter.binding.rank);