123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266 |
- /* *******************************************************************
- * Copyright (c) 2002-2010 Contributors
- * All rights reserved.
- * This program and the accompanying materials are made available
- * under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- * ******************************************************************/
- package org.aspectj.weaver;
-
- import java.io.IOException;
- import java.lang.reflect.Modifier;
- import java.util.ArrayList;
- import java.util.HashMap;
- import java.util.HashSet;
- import java.util.Iterator;
- import java.util.LinkedHashSet;
- import java.util.List;
- import java.util.Map;
- import java.util.Set;
-
- import org.aspectj.bridge.ISourceLocation;
-
- /**
- * Represent a resolved member. Components of it are expected to exist. This member will correspond to a real member *unless* it is
- * being used to represent the effect of an ITD.
- *
- * @author PARC
- * @author Andy Clement
- */
- public class ResolvedMemberImpl extends MemberImpl implements IHasPosition, ResolvedMember {
-
- private String[] parameterNames = null;
- private boolean isResolved = false;
- protected UnresolvedType[] checkedExceptions = UnresolvedType.NONE;
-
- /**
- * if this member is a parameterized version of a member in a generic type, then this field holds a reference to the member we
- * parameterize.
- */
- protected ResolvedMember backingGenericMember = null;
-
- protected AnnotationAJ[] annotations = null;
- protected ResolvedType[] annotationTypes = null;
- protected AnnotationAJ[][] parameterAnnotations = null;
- protected ResolvedType[][] parameterAnnotationTypes = null;
-
- // Some members are 'created' to represent other things (for example ITDs).
- // These members have their annotations stored elsewhere, and this flag indicates
- // that is the case. It is up to the caller to work out where that is!
- // Once determined the caller may choose to stash the annotations in this
- // member...
- private boolean isAnnotatedElsewhere = false;
- private boolean isAjSynthetic = false;
-
- // generic methods have type variables
- protected TypeVariable[] typeVariables;
-
- // these three fields hold the source location of this member
- protected int start, end;
- protected ISourceContext sourceContext = null;
-
- // XXX deprecate this in favor of the constructor below
- public ResolvedMemberImpl(MemberKind kind, UnresolvedType declaringType, int modifiers, UnresolvedType returnType, String name,
- UnresolvedType[] parameterTypes) {
- super(kind, declaringType, modifiers, returnType, name, parameterTypes);
- }
-
- public ResolvedMemberImpl(MemberKind kind, UnresolvedType declaringType, int modifiers, UnresolvedType returnType, String name,
- UnresolvedType[] parameterTypes, UnresolvedType[] checkedExceptions) {
- super(kind, declaringType, modifiers, returnType, name, parameterTypes);
- this.checkedExceptions = checkedExceptions;
- }
-
- public ResolvedMemberImpl(MemberKind kind, UnresolvedType declaringType, int modifiers, UnresolvedType returnType, String name,
- UnresolvedType[] parameterTypes, UnresolvedType[] checkedExceptions, ResolvedMember backingGenericMember) {
- this(kind, declaringType, modifiers, returnType, name, parameterTypes, checkedExceptions);
- this.backingGenericMember = backingGenericMember;
- this.isAjSynthetic = backingGenericMember.isAjSynthetic();
- }
-
- public ResolvedMemberImpl(MemberKind kind, UnresolvedType declaringType, int modifiers, String name, String signature) {
- super(kind, declaringType, modifiers, name, signature);
- }
-
- /**
- * Compute the full set of signatures for a member. This walks up the hierarchy giving the ResolvedMember in each defining type
- * in the hierarchy. A shadowMember can be created with a target type (declaring type) that does not actually define the member.
- * This is ok as long as the member is inherited in the declaring type. Each declaring type in the line to the actual declaring
- * type is added as an additional signature. For example:
- *
- * class A { void foo(); } class B extends A {}
- *
- * shadowMember : void B.foo()
- *
- * gives { void B.foo(), void A.foo() }
- *
- * @param joinPointSignature
- * @param inAWorld
- */
- public static JoinPointSignature[] getJoinPointSignatures(Member joinPointSignature, World inAWorld) {
-
- // Walk up hierarchy creating one member for each type up to and
- // including the
- // first defining type
- ResolvedType originalDeclaringType = joinPointSignature.getDeclaringType().resolve(inAWorld);
- ResolvedMemberImpl firstDefiningMember = (ResolvedMemberImpl) joinPointSignature.resolve(inAWorld);
- if (firstDefiningMember == null) {
- return JoinPointSignature.EMPTY_ARRAY;
- }
- // declaringType can be unresolved if we matched a synthetic member
- // generated by Aj...
- // should be fixed elsewhere but add this resolve call on the end for
- // now so that we can
- // focus on one problem at a time...
- ResolvedType firstDefiningType = firstDefiningMember.getDeclaringType().resolve(inAWorld);
- if (firstDefiningType != originalDeclaringType) {
- if (joinPointSignature.getKind() == Member.CONSTRUCTOR) {
- return JoinPointSignature.EMPTY_ARRAY;
- }
- // else if (shadowMember.isStatic()) {
- // return new ResolvedMember[] {firstDefiningMember};
- // }
- }
-
- List<ResolvedType> declaringTypes = new ArrayList<>();
- accumulateTypesInBetween(originalDeclaringType, firstDefiningType, declaringTypes);
- Set<ResolvedMember> memberSignatures = new LinkedHashSet<>();
- for (ResolvedType declaringType : declaringTypes) {
- memberSignatures.add(new JoinPointSignature(firstDefiningMember, declaringType));
- }
-
- if (shouldWalkUpHierarchyFor(firstDefiningMember)) {
- // now walk up the hierarchy from the firstDefiningMember and
- // include the signature for
- // every type between the firstDefiningMember and the root defining
- // member.
- Iterator<ResolvedType> superTypeIterator = firstDefiningType.getDirectSupertypes();
- List<ResolvedType> typesAlreadyVisited = new ArrayList<>();
- accumulateMembersMatching(firstDefiningMember, superTypeIterator, typesAlreadyVisited, memberSignatures, false);
- }
-
- JoinPointSignature[] ret = new JoinPointSignature[memberSignatures.size()];
- memberSignatures.toArray(ret);
- return ret;
- }
-
- private static boolean shouldWalkUpHierarchyFor(Member aMember) {
- if (aMember.getKind() == Member.CONSTRUCTOR) {
- return false;
- }
- if (aMember.getKind() == Member.FIELD) {
- return false;
- }
- if (Modifier.isStatic(aMember.getModifiers())) {
- return false;
- }
- return true;
- }
-
- /**
- * Build a list containing every type between subtype and supertype, inclusively.
- */
- private static void accumulateTypesInBetween(ResolvedType subType, ResolvedType superType, List<ResolvedType> types) {
- types.add(subType);
- if (subType == superType) {
- return;
- } else {
- for (Iterator<ResolvedType> iter = subType.getDirectSupertypes(); iter.hasNext();) {
- ResolvedType parent = iter.next();
- if (superType.isAssignableFrom(parent)) {
- accumulateTypesInBetween(parent, superType, types);
- }
- }
- }
- }
-
- /**
- * We have a resolved member, possibly with type parameter references as parameters or return type. We need to find all its
- * ancestor members. When doing this, a type parameter matches regardless of bounds (bounds can be narrowed down the hierarchy).
- */
- private static void accumulateMembersMatching(ResolvedMemberImpl memberToMatch, Iterator<ResolvedType> typesToLookIn,
- List<ResolvedType> typesAlreadyVisited, Set<ResolvedMember> foundMembers, boolean ignoreGenerics) {
- while (typesToLookIn.hasNext()) {
- ResolvedType toLookIn = typesToLookIn.next();
- if (!typesAlreadyVisited.contains(toLookIn)) {
- typesAlreadyVisited.add(toLookIn);
- ResolvedMemberImpl foundMember = (ResolvedMemberImpl) toLookIn.lookupResolvedMember(memberToMatch, true,
- ignoreGenerics);
- if (foundMember != null && isVisibleTo(memberToMatch, foundMember)) {
- List<ResolvedType> declaringTypes = new ArrayList<>();
- // declaring type can be unresolved if the member can from
- // an ITD...
- ResolvedType resolvedDeclaringType = foundMember.getDeclaringType().resolve(toLookIn.getWorld());
- accumulateTypesInBetween(toLookIn, resolvedDeclaringType, declaringTypes);
- for (ResolvedType declaringType : declaringTypes) {
- // typesAlreadyVisited.add(declaringType);
- foundMembers.add(new JoinPointSignature(foundMember, declaringType));
- }
- if (!ignoreGenerics && toLookIn.isParameterizedType() && (foundMember.backingGenericMember != null)) {
- foundMembers.add(new JoinPointSignature(foundMember.backingGenericMember, foundMember.declaringType
- .resolve(toLookIn.getWorld())));
- }
- accumulateMembersMatching(foundMember, toLookIn.getDirectSupertypes(), typesAlreadyVisited, foundMembers,
- ignoreGenerics);
- // if this was a parameterized type, look in the generic
- // type that backs it too
- }
- }
- }
- }
-
- /**
- * Returns true if the parent member is visible to the child member In the same declaring type this is always true, otherwise if
- * parent is private it is false.
- *
- * @param childMember
- * @param parentMember
- * @return
- */
- private static boolean isVisibleTo(ResolvedMember childMember, ResolvedMember parentMember) {
- if (childMember.getDeclaringType().equals(parentMember.getDeclaringType())) {
- return true;
- }
- if (Modifier.isPrivate(parentMember.getModifiers())) {
- return false;
- } else {
- return true;
- }
- }
-
- // ----
-
- @Override
- public final int getModifiers(World world) {
- return modifiers;
- }
-
- @Override
- public final int getModifiers() {
- return modifiers;
- }
-
- // ----
-
- @Override
- public final UnresolvedType[] getExceptions(World world) {
- return getExceptions();
- }
-
- public UnresolvedType[] getExceptions() {
- return checkedExceptions;
- }
-
- public ShadowMunger getAssociatedShadowMunger() {
- return null;
- }
-
- // ??? true or false?
- public boolean isAjSynthetic() {
- return isAjSynthetic;
- }
-
- protected void setAjSynthetic(boolean b) {
- isAjSynthetic = b;
- }
-
- public boolean hasAnnotations() {
- return (annotationTypes != null);
- }
-
- /**
- * Check if this member has an annotation of the specified type. If the member has a backing generic member then this member
- * represents a parameterization of a member in a generic type and the annotations available on the backing generic member
- * should be used.
- *
- * @param ofType the type of the annotation being searched for
- * @return true if the annotation is found on this member or its backing generic member
- */
- public boolean hasAnnotation(UnresolvedType ofType) {
- // The ctors don't allow annotations to be specified ... yet - but
- // that doesn't mean it is an error to call this method.
- // Normally the weaver will be working with subtypes of
- // this type - BcelField/BcelMethod
- if (backingGenericMember != null) {
- if (annotationTypes != null) {
- throw new BCException("Unexpectedly found a backing generic member and a local set of annotations");
- }
- return backingGenericMember.hasAnnotation(ofType);
- }
- if (annotationTypes != null) {
- for (ResolvedType annotationType : annotationTypes) {
- if (annotationType.equals(ofType)) {
- return true;
- }
- }
- }
- return false;
- }
-
- public ResolvedType[] getAnnotationTypes() {
- // The ctors don't allow annotations to be specified ... yet - but
- // that doesn't mean it is an error to call this method.
- // Normally the weaver will be working with subtypes of
- // this type - BcelField/BcelMethod
- if (backingGenericMember != null) {
- if (annotationTypes != null) {
- throw new BCException("Unexpectedly found a backing generic member and a local set of annotations");
- }
- return backingGenericMember.getAnnotationTypes();
- }
- return annotationTypes;
- }
-
- public String getAnnotationDefaultValue() {
- throw new UnsupportedOperationException(
- "You should resolve this member and call getAnnotationDefaultValue() on the result...");
- }
-
- @Override
- public AnnotationAJ[] getAnnotations() {
- if (backingGenericMember != null) {
- return backingGenericMember.getAnnotations();
- }
- if (annotations!=null) {
- return annotations;
- }
- return super.getAnnotations();
- }
-
- public AnnotationAJ getAnnotationOfType(UnresolvedType ofType) {
- if (annotations!=null) {
- // this means they have been set (we are likely a placeholder for an ITD, so a fake member)
- for (AnnotationAJ annotation: annotations) {
- if (annotation.getType().equals(ofType)) {
- return annotation;
- }
- }
- return null;
- }
- throw new UnsupportedOperationException("You should resolve this member and call getAnnotationOfType() on the result...");
- }
-
- public void setAnnotations(AnnotationAJ[] annotations) {
- this.annotations = annotations;
- }
-
- public void setAnnotationTypes(ResolvedType[] annotationTypes) {
- this.annotationTypes = annotationTypes;
- }
-
- public ResolvedType[][] getParameterAnnotationTypes() {
- return parameterAnnotationTypes;
- }
-
- public AnnotationAJ[][] getParameterAnnotations() {
- if (backingGenericMember != null) {
- return backingGenericMember.getParameterAnnotations();
- }
- throw new BCException("Cannot return parameter annotations for a " + this.getClass().getName() + " member");
- // return super.getParameterAnnotations();
- }
-
- public void addAnnotation(AnnotationAJ annotation) {
- if (annotationTypes == null) {
- annotationTypes = new ResolvedType[1];
- annotationTypes[0] = annotation.getType();
- annotations = new AnnotationAJ[1];
- annotations[0] = annotation;
- } else {
- int len = annotations.length;
- AnnotationAJ[] ret = new AnnotationAJ[len + 1];
- System.arraycopy(annotations, 0, ret, 0, len);
- ret[len] = annotation;
- annotations = ret;
-
- ResolvedType[] newAnnotationTypes = new ResolvedType[len + 1];
- System.arraycopy(annotationTypes, 0, newAnnotationTypes, 0, len);
- newAnnotationTypes[len] = annotation.getType();
- annotationTypes = newAnnotationTypes;
- }
- }
-
- public boolean isBridgeMethod() {
- return (modifiers & Constants.ACC_BRIDGE) != 0 && getKind().equals(METHOD);
- }
-
- public boolean isVarargsMethod() {
- return (modifiers & Constants.ACC_VARARGS) != 0;
- }
-
- public void setVarargsMethod() {
- modifiers = modifiers | Constants.ACC_VARARGS;
- }
-
- public boolean isSynthetic() {
- // See Bcelmethod.isSynthetic() which takes account of preJava5
- // Synthetic modifier
- return (modifiers & 4096) != 0; // do we know better?
- }
-
- public void write(CompressingDataOutputStream s) throws IOException {
- getKind().write(s);
- s.writeBoolean(s.canCompress()); // boolean indicates if parts of this are compressed references
-
- // write out the signature of the declaring type of this member
- if (s.canCompress()) {
- s.writeCompressedSignature(getDeclaringType().getSignature());
- } else {
- getDeclaringType().write(s);
- }
-
- // write out the modifiers
- s.writeInt(modifiers);
-
- // write out the name and the signature of this member
- if (s.canCompress()) {
- s.writeCompressedName(getName());
- s.writeCompressedSignature(getSignature());
- } else {
- s.writeUTF(getName());
- s.writeUTF(getSignature());
- }
-
- // write out the array clauses
- UnresolvedType.writeArray(getExceptions(), s);
-
- s.writeInt(getStart());
- s.writeInt(getEnd());
- s.writeBoolean(isVarargsMethod());
-
- // Write out any type variables...
- if (typeVariables == null) {
- s.writeByte(0);
- } else {
- s.writeByte(typeVariables.length);
- for (TypeVariable typeVariable : typeVariables) {
- typeVariable.write(s);
- }
- }
- String gsig = getGenericSignature();
-
- // change this to a byte: 255=false 0>254 means true and encodes the number of parameters
- if (getSignature().equals(gsig)) {
- s.writeByte(0xff);
- } else {
- s.writeByte(parameterTypes.length);
- for (UnresolvedType parameterType : parameterTypes) {
- if (s.canCompress()) {
- s.writeCompressedSignature(parameterType.getSignature());
- } else {
- UnresolvedType array_element = parameterType;
- array_element.write(s);
- }
- }
- if (s.canCompress()) {
- s.writeCompressedSignature(returnType.getSignature());
- } else {
- returnType.write(s);
- }
- }
- }
-
- /**
- * Return the member generic signature that would be suitable for inclusion in a class file Signature attribute. For: <T>
- * List<String> getThem(T t) {} we would create: <T:Ljava/lang/Object;>(TT;)Ljava/util/List<Ljava/lang/String;>;;
- *
- * @return the generic signature for the member that could be inserted into a class file
- */
- public String getSignatureForAttribute() {
- StringBuffer sb = new StringBuffer();
- if (typeVariables != null) {
- sb.append("<");
- for (TypeVariable typeVariable : typeVariables) {
- sb.append(typeVariable.getSignatureForAttribute()); // need
- // a
- // 'getSignatureForAttribute()'
- }
- sb.append(">");
- }
- sb.append("(");
- for (UnresolvedType parameterType : parameterTypes) {
- ResolvedType ptype = (ResolvedType) parameterType;
- sb.append(ptype.getSignatureForAttribute());
- }
- sb.append(")");
- sb.append(((ResolvedType) returnType).getSignatureForAttribute());
- return sb.toString();
- }
-
- public String getGenericSignature() {
- StringBuffer sb = new StringBuffer();
- if (typeVariables != null) {
- sb.append("<");
- for (TypeVariable typeVariable : typeVariables) {
- sb.append(typeVariable.getSignature());
- }
- sb.append(">");
- }
- sb.append("(");
- for (UnresolvedType ptype : parameterTypes) {
- sb.append(ptype.getSignature());
- }
- sb.append(")");
- sb.append(returnType.getSignature());
- return sb.toString();
- }
-
- public static void writeArray(ResolvedMember[] members, CompressingDataOutputStream s) throws IOException {
- s.writeInt(members.length);
- for (ResolvedMember member : members) {
- member.write(s);
- }
- }
-
- public static ResolvedMemberImpl readResolvedMember(VersionedDataInputStream s, ISourceContext sourceContext)
- throws IOException {
-
- MemberKind mk = MemberKind.read(s);
- boolean compressed = (s.isAtLeast169() ? s.readBoolean() : false);
- UnresolvedType declaringType = compressed ? UnresolvedType.forSignature(s.readUtf8(s.readShort())) : UnresolvedType.read(s);
- int modifiers = s.readInt();
- String name = compressed ? s.readUtf8(s.readShort()) : s.readUTF();
- String signature = compressed ? s.readUtf8(s.readShort()) : s.readUTF();
- ResolvedMemberImpl m = new ResolvedMemberImpl(mk, declaringType, modifiers, name, signature);
- m.checkedExceptions = UnresolvedType.readArray(s);
-
- m.start = s.readInt();
- m.end = s.readInt();
- m.sourceContext = sourceContext;
-
- if (s.getMajorVersion() >= AjAttribute.WeaverVersionInfo.WEAVER_VERSION_MAJOR_AJ150) {
-
- if (s.getMajorVersion() >= AjAttribute.WeaverVersionInfo.WEAVER_VERSION_MAJOR_AJ150M4) {
- boolean isvarargs = s.readBoolean();
- if (isvarargs) {
- m.setVarargsMethod();
- }
- }
-
- int tvcount = s.isAtLeast169() ? s.readByte() : s.readInt();
- if (tvcount != 0) {
- m.typeVariables = new TypeVariable[tvcount];
- for (int i = 0; i < tvcount; i++) {
- m.typeVariables[i] = TypeVariable.read(s);
- m.typeVariables[i].setDeclaringElement(m);
- m.typeVariables[i].setRank(i);
- }
- }
- if (s.getMajorVersion() >= AjAttribute.WeaverVersionInfo.WEAVER_VERSION_MAJOR_AJ150M4) {
- int pcount = -1;
- boolean hasAGenericSignature = false;
- if (s.isAtLeast169()) {
- pcount = s.readByte();
- hasAGenericSignature = (pcount >= 0 && pcount < 255);
- } else {
- hasAGenericSignature = s.readBoolean();
- }
- if (hasAGenericSignature) {
- int ps = (s.isAtLeast169() ? pcount : s.readInt());
- UnresolvedType[] params = new UnresolvedType[ps];
- for (int i = 0; i < params.length; i++) {
- if (compressed) {
- params[i] = TypeFactory.createTypeFromSignature(s.readSignature());
- } else {
- params[i] = TypeFactory.createTypeFromSignature(s.readUTF());
- }
- }
- UnresolvedType rt = compressed ? TypeFactory.createTypeFromSignature(s.readSignature()) : TypeFactory
- .createTypeFromSignature(s.readUTF());
- m.parameterTypes = params;
- m.returnType = rt;
- }
- }
- }
- return m;
- }
-
- public static ResolvedMember[] readResolvedMemberArray(VersionedDataInputStream s, ISourceContext context) throws IOException {
- int len = s.readInt();
- ResolvedMember[] members = new ResolvedMember[len];
- for (int i = 0; i < len; i++) {
- members[i] = ResolvedMemberImpl.readResolvedMember(s, context);
- }
- return members;
- }
-
- // OPTIMIZE dont like how resolve(world) on ResolvedMemberImpl does
- // something different to world.resolve(member)
- @Override
- public ResolvedMember resolve(World world) {
- if (isResolved) {
- return this;
- }
- // make sure all the pieces of a resolvedmember really are resolved
- try {
- if (typeVariables != null && typeVariables.length > 0) {
- for (int i = 0; i < typeVariables.length; i++) {
- typeVariables[i] = typeVariables[i].resolve(world);
- }
- }
- world.setTypeVariableLookupScope(this);
- // if (annotationTypes != null) {
- // Set<ResolvedType> r = new HashSet<ResolvedType>();
- // for (UnresolvedType element : annotationTypes) {
- // // for (Iterator iter = annotationTypes.iterator(); iter.hasNext();) {
- // // UnresolvedType element = (UnresolvedType) iter.next();
- // r.add(world.resolve(element));
- // }
- // annotationTypes = r;
- // }
- declaringType = declaringType.resolve(world);
- if (declaringType.isRawType()) {
- declaringType = ((ReferenceType) declaringType).getGenericType();
- }
-
- if (parameterTypes != null && parameterTypes.length > 0) {
- for (int i = 0; i < parameterTypes.length; i++) {
- parameterTypes[i] = parameterTypes[i].resolve(world);
- }
- }
-
- returnType = returnType.resolve(world);
-
- } finally {
- world.setTypeVariableLookupScope(null);
- }
- isResolved = true;
- return this;
- }
-
- public ISourceContext getSourceContext(World world) {
- return getDeclaringType().resolve(world).getSourceContext();
- }
-
- public String[] getParameterNames() {
- return parameterNames;
- }
-
- public final void setParameterNames(String[] pnames) {
- parameterNames = pnames;
- }
-
- @Override
- public final String[] getParameterNames(World world) {
- return getParameterNames();
- }
-
- public AjAttribute.EffectiveSignatureAttribute getEffectiveSignature() {
- return null;
- }
-
- public ISourceLocation getSourceLocation() {
- // System.out.println("get context: " + this + " is " + sourceContext);
- if (getSourceContext() == null) {
- // System.err.println("no context: " + this);
- return null;
- }
- return getSourceContext().makeSourceLocation(this);
- }
-
- public int getEnd() {
- return end;
- }
-
- public ISourceContext getSourceContext() {
- return sourceContext;
- }
-
- public int getStart() {
- return start;
- }
-
- public void setPosition(int sourceStart, int sourceEnd) {
- this.start = sourceStart;
- this.end = sourceEnd;
- }
-
- public void setDeclaringType(ReferenceType rt) {
- declaringType = rt;
- }
-
- public void setSourceContext(ISourceContext sourceContext) {
- this.sourceContext = sourceContext;
- }
-
- public boolean isAbstract() {
- return Modifier.isAbstract(modifiers);
- }
-
- public boolean isPublic() {
- return Modifier.isPublic(modifiers);
- }
-
- public boolean isDefault() {
- int mods = getModifiers();
- return !(Modifier.isPublic(mods) || Modifier.isProtected(mods) || Modifier.isPrivate(mods));
- }
-
- public boolean isVisible(ResolvedType fromType) {
- UnresolvedType declaringType = getDeclaringType();
- ResolvedType type = null;
- if (fromType.equals(declaringType)) {
- type = fromType;
- } else {
- World world = fromType.getWorld();
- type = declaringType.resolve(world);
- }
- return ResolvedType.isVisible(getModifiers(), type, fromType);
- }
-
- public void setCheckedExceptions(UnresolvedType[] checkedExceptions) {
- this.checkedExceptions = checkedExceptions;
- }
-
- public void setAnnotatedElsewhere(boolean b) {
- isAnnotatedElsewhere = b;
- }
-
- public boolean isAnnotatedElsewhere() {
- return isAnnotatedElsewhere;
- }
-
- /**
- * Get the UnresolvedType for the return type, taking generic signature into account
- */
- @Override
- public UnresolvedType getGenericReturnType() {
- return getReturnType();
- }
-
- /**
- * Get the TypeXs of the parameter types, taking generic signature into account
- */
- @Override
- public UnresolvedType[] getGenericParameterTypes() {
- return getParameterTypes();
- }
-
- public ResolvedMemberImpl parameterizedWith(UnresolvedType[] typeParameters, ResolvedType newDeclaringType,
- boolean isParameterized) {
- return parameterizedWith(typeParameters, newDeclaringType, isParameterized, null);
- }
-
- /**
- * Return a resolvedmember in which all the type variables in the signature have been replaced with the given bindings. The
- * 'isParameterized' flag tells us whether we are creating a raw type version or not. if (isParameterized) then List<T> will
- * turn into List<String> (for example) - if (!isParameterized) then List<T> will turn into List.
- */
- public ResolvedMemberImpl parameterizedWith(UnresolvedType[] typeParameters, ResolvedType newDeclaringType,
- boolean isParameterized, List<String> aliases) {
- // PR308773
- // this check had problems for the inner type of a generic type because the inner type can be represented
- // by a 'simple type' if it is only sharing type variables with the outer and has none of its own. To avoid the
- // check going bang in this case we check for $ (crap...) - we can't check the outer because the declaring type
- // is considered unresolved...
- if (// isParameterized && <-- might need this bit...
- !getDeclaringType().isGenericType() && !getDeclaringType().getName().contains("$")) {
- throw new IllegalStateException("Can't ask to parameterize a member of non-generic type: " + getDeclaringType()
- + " kind(" + getDeclaringType().typeKind + ")");
- }
- TypeVariable[] typeVariables = getDeclaringType().getTypeVariables();
- if (isParameterized && (typeVariables.length != typeParameters.length)) {
- throw new IllegalStateException("Wrong number of type parameters supplied");
- }
- Map<String, UnresolvedType> typeMap = new HashMap<>();
- boolean typeParametersSupplied = typeParameters != null && typeParameters.length > 0;
- if (typeVariables != null) {
- // If no 'replacements' were supplied in the typeParameters array
- // then collapse
- // type variables to their first bound.
- for (int i = 0; i < typeVariables.length; i++) {
- UnresolvedType ut = (!typeParametersSupplied ? typeVariables[i].getFirstBound() : typeParameters[i]);
- typeMap.put(typeVariables[i].getName(), ut);
- }
- }
- // For ITDs on generic types that use type variables from the target type, the aliases
- // record the alternative names used throughout the ITD expression that must map to
- // the same value as the type variables real name.
- if (aliases != null) {
- int posn = 0;
- for (String typeVariableAlias : aliases) {
- typeMap.put(typeVariableAlias, (!typeParametersSupplied ? typeVariables[posn].getFirstBound()
- : typeParameters[posn]));
- posn++;
- }
- }
-
- UnresolvedType parameterizedReturnType = parameterize(getGenericReturnType(), typeMap, isParameterized,
- newDeclaringType.getWorld());
- UnresolvedType[] parameterizedParameterTypes = new UnresolvedType[getGenericParameterTypes().length];
- UnresolvedType[] genericParameterTypes = getGenericParameterTypes();
- for (int i = 0; i < parameterizedParameterTypes.length; i++) {
- parameterizedParameterTypes[i] = parameterize(genericParameterTypes[i], typeMap, isParameterized,
- newDeclaringType.getWorld());
- }
- ResolvedMemberImpl ret = new ResolvedMemberImpl(getKind(), newDeclaringType, getModifiers(), parameterizedReturnType,
- getName(), parameterizedParameterTypes, getExceptions(), this);
- ret.setTypeVariables(getTypeVariables());
- ret.setSourceContext(getSourceContext());
- ret.setPosition(getStart(), getEnd());
- ret.setParameterNames(getParameterNames());
- return ret;
- }
-
- /**
- * Replace occurrences of type variables in the signature with values contained in the map. The map is of the form
- * A=String,B=Integer and so a signature List<A> Foo.m(B i) {} would become List<String> Foo.m(Integer i) {}
- */
- public ResolvedMember parameterizedWith(Map<String, UnresolvedType> m, World w) {
- // if (//isParameterized && <-- might need this bit...
- // !getDeclaringType().isGenericType()) {
- // throw new IllegalStateException(
- // "Can't ask to parameterize a member of non-generic type: "
- // +getDeclaringType()+" kind("+
- // getDeclaringType().typeKind+")");
- // }
- declaringType = declaringType.resolve(w);
- if (declaringType.isRawType()) {
- declaringType = ((ResolvedType) declaringType).getGenericType();
- // TypeVariable[] typeVariables = getDeclaringType().getTypeVariables();
- // if (isParameterized && (typeVariables.length !=
- // typeParameters.length)) {
- // throw new
- // IllegalStateException("Wrong number of type parameters supplied");
- // }
- // Map typeMap = new HashMap();
- // boolean typeParametersSupplied = typeParameters!=null &&
- // typeParameters.length>0;
- // if (typeVariables!=null) {
- // // If no 'replacements' were supplied in the typeParameters array
- // then collapse
- // // type variables to their first bound.
- // for (int i = 0; i < typeVariables.length; i++) {
- // UnresolvedType ut =
- // (!typeParametersSupplied?typeVariables[i].getFirstBound
- // ():typeParameters[i]);
- // typeMap.put(typeVariables[i].getName(),ut);
- // }
- // }
- // // For ITDs on generic types that use type variables from the target
- // type, the aliases
- // // record the alternative names used throughout the ITD expression
- // that must map to
- // // the same value as the type variables real name.
- // if (aliases!=null) {
- // int posn = 0;
- // for (Iterator iter = aliases.iterator(); iter.hasNext();) {
- // String typeVariableAlias = (String) iter.next();
- // typeMap.put(typeVariableAlias,(!typeParametersSupplied?typeVariables[
- // posn].getFirstBound():typeParameters[posn]));
- // posn++;
- // }
- // }
- }
-
- UnresolvedType parameterizedReturnType = parameterize(getGenericReturnType(), m, true, w);
- UnresolvedType[] parameterizedParameterTypes = new UnresolvedType[getGenericParameterTypes().length];
- UnresolvedType[] genericParameterTypes = getGenericParameterTypes();
- for (int i = 0; i < parameterizedParameterTypes.length; i++) {
- parameterizedParameterTypes[i] = parameterize(genericParameterTypes[i], m, true, w);
- }
- ResolvedMemberImpl ret = new ResolvedMemberImpl(getKind(), declaringType, getModifiers(), parameterizedReturnType,
- getName(), parameterizedParameterTypes, getExceptions(), this);
- ret.setTypeVariables(getTypeVariables());
- ret.setSourceContext(getSourceContext());
- ret.setPosition(getStart(), getEnd());
- ret.setParameterNames(getParameterNames());
- return ret;
- }
-
- public void setTypeVariables(TypeVariable[] tvars) {
- typeVariables = tvars;
- }
-
- public TypeVariable[] getTypeVariables() {
- return typeVariables;
- }
-
- protected UnresolvedType parameterize(UnresolvedType aType, Map<String, UnresolvedType> typeVariableMap,
- boolean inParameterizedType, World w) {
- if (aType instanceof TypeVariableReference) {
- String variableName = ((TypeVariableReference) aType).getTypeVariable().getName();
- if (!typeVariableMap.containsKey(variableName)) {
- return aType; // if the type variable comes from the method (and
- // not the type) thats OK
- }
- return typeVariableMap.get(variableName);
- } else if (aType.isParameterizedType()) {
- if (inParameterizedType) {
- if (w != null) {
- aType = aType.resolve(w);
- } else {
- UnresolvedType dType = getDeclaringType();
- aType = aType.resolve(((ResolvedType) dType).getWorld());
- }
- return aType.parameterize(typeVariableMap);
- } else {
- return aType.getRawType();
- }
- } else if (aType.isArray()) {
- // The component type might be a type variable (pr150095)
- int dims = 1;
- String sig = aType.getSignature();
- // while (sig.charAt(dims) == '[')
- // dims++;
- UnresolvedType arrayType = null;
- UnresolvedType componentSig = UnresolvedType.forSignature(sig.substring(dims));
- UnresolvedType parameterizedComponentSig = parameterize(componentSig, typeVariableMap, inParameterizedType, w);
- if (parameterizedComponentSig.isTypeVariableReference()
- && parameterizedComponentSig instanceof UnresolvedTypeVariableReferenceType
- && typeVariableMap.containsKey(((UnresolvedTypeVariableReferenceType) parameterizedComponentSig)
- .getTypeVariable().getName())) { // pr250632
- // TODO ASC bah, this code is rubbish - i should fix it properly
- StringBuffer newsig = new StringBuffer();
- newsig.append("[T");
- newsig.append(((UnresolvedTypeVariableReferenceType) parameterizedComponentSig).getTypeVariable().getName());
- newsig.append(";");
- arrayType = UnresolvedType.forSignature(newsig.toString());
- } else {
- arrayType = ResolvedType.makeArray(parameterizedComponentSig, dims);
- }
- return arrayType;
- }
- return aType;
- }
-
- /**
- * If this member is defined by a parameterized super-type, return the erasure of that member. For example: interface I<T> { T
- * foo(T aTea); } class C implements I<String> { String foo(String aString) { return "something"; } } The resolved member for
- * C.foo has signature String foo(String). The erasure of that member is Object foo(Object) -- use upper bound of type variable.
- * A type is a supertype of itself.
- */
- // public ResolvedMember getErasure() {
- // if (calculatedMyErasure) return myErasure;
- // calculatedMyErasure = true;
- // ResolvedType resolvedDeclaringType = (ResolvedType) getDeclaringType();
- // // this next test is fast, and the result is cached.
- // if (!resolvedDeclaringType.hasParameterizedSuperType()) {
- // return null;
- // } else {
- // // we have one or more parameterized super types.
- // // this member may be defined by one of them... we need to find out.
- // Collection declaringTypes =
- // this.getDeclaringTypes(resolvedDeclaringType.getWorld());
- // for (Iterator iter = declaringTypes.iterator(); iter.hasNext();) {
- // ResolvedType aDeclaringType = (ResolvedType) iter.next();
- // if (aDeclaringType.isParameterizedType()) {
- // // we've found the (a?) parameterized type that defines this member.
- // // now get the erasure of it
- // ResolvedMemberImpl matchingMember = (ResolvedMemberImpl)
- // aDeclaringType.lookupMemberNoSupers(this);
- // if (matchingMember != null && matchingMember.backingGenericMember !=
- // null) {
- // myErasure = matchingMember.backingGenericMember;
- // return myErasure;
- // }
- // }
- // }
- // }
- // return null;
- // }
- //
- // private ResolvedMember myErasure = null;
- // private boolean calculatedMyErasure = false;
- public boolean hasBackingGenericMember() {
- return backingGenericMember != null;
- }
-
- public ResolvedMember getBackingGenericMember() {
- return backingGenericMember;
- }
-
- /**
- * For ITDs, we use the default factory methods to build a resolved member, then alter a couple of characteristics using this
- * method - this is safe.
- */
- public void resetName(String newName) {
- this.name = newName;
- }
-
- public void resetKind(MemberKind newKind) {
- this.kind = newKind;
- }
-
- public void resetModifiers(int newModifiers) {
- this.modifiers = newModifiers;
- }
-
- public void resetReturnTypeToObjectArray() {
- returnType = UnresolvedType.OBJECTARRAY;
- }
-
- /**
- * Returns true if this member matches the other. The matching takes into account name and parameter types only. When comparing
- * parameter types, we allow any type variable to match any other type variable regardless of bounds.
- */
- public boolean matches(ResolvedMember aCandidateMatch, boolean ignoreGenerics) {
- ResolvedMemberImpl candidateMatchImpl = (ResolvedMemberImpl) aCandidateMatch;
- if (!getName().equals(aCandidateMatch.getName())) {
- return false;
- }
- UnresolvedType[] parameterTypes = getGenericParameterTypes();
- UnresolvedType[] candidateParameterTypes = aCandidateMatch.getGenericParameterTypes();
- if (parameterTypes.length != candidateParameterTypes.length) {
- return false;
- }
- boolean b = false;
- /*
- * if (ignoreGenerics) { String myParameterSignature = getParameterSigWithBoundsRemoved(); String
- * candidateParameterSignature = candidateMatchImpl.getParameterSigWithBoundsRemoved(); if
- * (myParameterSignature.equals(candidateParameterSignature)) { b = true; } else { myParameterSignature =
- * (hasBackingGenericMember() ? backingGenericMember.getParameterSignatureErased() : getParameterSignatureErased());
- * candidateParameterSignature = (candidateMatchImpl.hasBackingGenericMember() ? candidateMatchImpl.backingGenericMember
- * .getParameterSignatureErased() : candidateMatchImpl.getParameterSignatureErased()); // System.out.println("my psig = " +
- * myParameterSignature); // System.out.println("can psig = " + candidateParameterSignature); b =
- * myParameterSignature.equals(candidateParameterSignature); } } else {
- */
- String myParameterSignature = getParameterSigWithBoundsRemoved();
- String candidateParameterSignature = candidateMatchImpl.getParameterSigWithBoundsRemoved();
- if (myParameterSignature.equals(candidateParameterSignature)) {
- b = true;
- } else {
- // try erasure
- myParameterSignature = getParameterSignatureErased();
- candidateParameterSignature = candidateMatchImpl.getParameterSignatureErased();
- // myParameterSignature = (hasBackingGenericMember() ? backingGenericMember.getParameterSignatureErased()
- // : getParameterSignatureErased());
- // candidateParameterSignature = (candidateMatchImpl.hasBackingGenericMember() ?
- // candidateMatchImpl.backingGenericMember
- // .getParameterSignatureErased() : candidateMatchImpl.getParameterSignatureErased());
- // System.out.println("my psig = " + myParameterSignature);
- // System.out.println("can psig = " + candidateParameterSignature);
- b = myParameterSignature.equals(candidateParameterSignature);
- // }
- }
- // System.out.println("Checking param signatures: " + b);
- return b;
- }
-
- /**
- * converts e.g. <T extends Number>.... List<T> to just Ljava/util/List<T;>; whereas the full signature would be
- * Ljava/util/List<T:Ljava/lang/Number;>;
- */
- private String myParameterSignatureWithBoundsRemoved = null;
- /**
- * converts e.g. <T extends Number>.... List<T> to just Ljava/util/List;
- */
- private String myParameterSignatureErasure = null;
-
- // does NOT produce a meaningful java signature, but does give a unique
- // string suitable for
- // comparison.
- private String getParameterSigWithBoundsRemoved() {
- if (myParameterSignatureWithBoundsRemoved != null) {
- return myParameterSignatureWithBoundsRemoved;
- }
- StringBuffer sig = new StringBuffer();
- UnresolvedType[] myParameterTypes = getGenericParameterTypes();
- for (UnresolvedType myParameterType : myParameterTypes) {
- appendSigWithTypeVarBoundsRemoved(myParameterType, sig, new HashSet<>());
- }
- myParameterSignatureWithBoundsRemoved = sig.toString();
- return myParameterSignatureWithBoundsRemoved;
- }
-
- /**
- * Return the erased form of the signature with bounds collapsed for type variables, etc. Does not include the return type, @see
- * getParam
- */
- public String getParameterSignatureErased() {
- if (myParameterSignatureErasure == null) {
- StringBuilder sig = new StringBuilder();
- for (UnresolvedType parameter : getParameterTypes()) {
- sig.append(parameter.getErasureSignature());
- }
- myParameterSignatureErasure = sig.toString();
- }
- return myParameterSignatureErasure;
- }
-
- public String getSignatureErased() {
- StringBuffer sb = new StringBuffer();
- sb.append("(");
- sb.append(getParameterSignatureErased());
- sb.append(")");
- sb.append(getReturnType().getErasureSignature());
- return sb.toString();
- }
-
- // does NOT produce a meaningful java signature, but does give a unique
- // string suitable for
- // comparison.
- public static void appendSigWithTypeVarBoundsRemoved(UnresolvedType aType, StringBuffer toBuffer,
- Set<UnresolvedType> alreadyUsedTypeVars) {
- if (aType.isTypeVariableReference()) {
- TypeVariableReferenceType typeVariableRT = (TypeVariableReferenceType) aType;
- // pr204505
- if (alreadyUsedTypeVars.contains(aType)) {
- toBuffer.append("...");
- } else {
- alreadyUsedTypeVars.add(aType);
- appendSigWithTypeVarBoundsRemoved(typeVariableRT.getTypeVariable().getFirstBound(), toBuffer, alreadyUsedTypeVars);
- }
- // toBuffer.append("T;");
- } else if (aType.isParameterizedType()) {
- toBuffer.append(aType.getRawType().getSignature());
- toBuffer.append("<");
- for (int i = 0; i < aType.getTypeParameters().length; i++) {
- appendSigWithTypeVarBoundsRemoved(aType.getTypeParameters()[i], toBuffer, alreadyUsedTypeVars);
- }
- toBuffer.append(">;");
- } else {
- toBuffer.append(aType.getSignature());
- }
- }
-
- /**
- * Useful for writing tests, returns *everything* we know about this member.
- */
- public String toDebugString() {
- StringBuffer r = new StringBuffer();
-
- // modifiers
- int mods = modifiers;
- if ((mods & 4096) > 0) {
- mods = mods - 4096; // remove synthetic (added in the ASM case but
- }
- // not in the BCEL case...)
- if ((mods & 512) > 0) {
- mods = mods - 512; // remove interface (added in the BCEL case but
- }
- // not in the ASM case...)
- if ((mods & 131072) > 0) {
- mods = mods - 131072; // remove deprecated (added in the ASM case
- }
- // but not in the BCEL case...)
- String modsStr = Modifier.toString(mods);
- if (modsStr.length() != 0) {
- r.append(modsStr).append("(" + mods + ")").append(" ");
- }
-
- // type variables
- if (typeVariables != null && typeVariables.length > 0) {
- r.append("<");
- for (int i = 0; i < typeVariables.length; i++) {
- if (i > 0) {
- r.append(",");
- }
- TypeVariable t = typeVariables[i];
- r.append(t.toDebugString());
- }
- r.append("> ");
- }
-
- // 'declaring' type
- r.append(getGenericReturnType().toDebugString());
- r.append(' ');
-
- // name
- r.append(declaringType.getName());
- r.append('.');
- r.append(name);
-
- // parameter signature if a method
- if (kind != FIELD) {
- r.append("(");
- UnresolvedType[] params = getGenericParameterTypes();
- boolean parameterNamesExist = showParameterNames && parameterNames != null && parameterNames.length == params.length;
- if (params.length != 0) {
- for (int i = 0, len = params.length; i < len; i++) {
- if (i > 0) {
- r.append(", ");
- }
- r.append(params[i].toDebugString());
- if (parameterNamesExist) {
- r.append(" ").append(parameterNames[i]);
- }
- }
- }
- r.append(")");
- }
- return r.toString();
- }
-
- // SECRETAPI - controlling whether parameter names come out in the debug
- // string (for testing purposes)
- public static boolean showParameterNames = true;
-
- public String toGenericString() {
- StringBuffer buf = new StringBuffer();
- buf.append(getGenericReturnType().getSimpleName());
- buf.append(' ');
- buf.append(declaringType.getName());
- buf.append('.');
- buf.append(name);
- if (kind != FIELD) {
- buf.append("(");
- UnresolvedType[] params = getGenericParameterTypes();
- if (params.length != 0) {
- buf.append(params[0].getSimpleName());
- for (int i = 1, len = params.length; i < len; i++) {
- buf.append(", ");
- buf.append(params[i].getSimpleName());
- }
- }
- buf.append(")");
- }
- return buf.toString();
- }
-
- public boolean isCompatibleWith(Member am) {
- if (kind != METHOD || am.getKind() != METHOD) {
- return true;
- }
- if (!name.equals(am.getName())) {
- return true;
- }
- if (!equalTypes(getParameterTypes(), am.getParameterTypes())) {
- return true;
- }
- return getReturnType().equals(am.getReturnType());
- }
-
- private static boolean equalTypes(UnresolvedType[] a, UnresolvedType[] b) {
- int len = a.length;
- if (len != b.length) {
- return false;
- }
- for (int i = 0; i < len; i++) {
- if (!a[i].equals(b[i])) {
- return false;
- }
- }
- return true;
- }
-
- public TypeVariable getTypeVariableNamed(String name) {
- // Check locally...
- if (typeVariables != null) {
- for (TypeVariable typeVariable : typeVariables) {
- if (typeVariable.getName().equals(name)) {
- return typeVariable;
- }
- }
- }
- // check the declaring type!
- return declaringType.getTypeVariableNamed(name);
-
- // Do generic aspects with ITDs that share type variables with the
- // aspect and the target type and have their own tvars cause
- // this to be messier?
- }
-
- public void evictWeavingState() {
- }
-
-
- public boolean isEquivalentTo(Object other) {
- return this.equals(other);
- }
-
- public boolean isDefaultConstructor() {
- return false;
- }
- }
|