import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import org.aspectj.ajdt.internal.compiler.ast.AspectDeclaration;
import org.aspectj.ajdt.internal.compiler.ast.PointcutDeclaration;
import org.aspectj.bridge.WeaveMessage;
import org.aspectj.org.eclipse.jdt.core.compiler.CharOperation;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Annotation;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.aspectj.org.eclipse.jdt.internal.compiler.env.AccessRestriction;
import org.aspectj.org.eclipse.jdt.internal.compiler.env.IBinaryType;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ClassScope;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
+import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.PackageBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
+import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TagBits;
+import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
import org.aspectj.weaver.AsmRelationshipProvider;
import org.aspectj.weaver.ConcreteTypeMunger;
import org.aspectj.weaver.ResolvedTypeMunger;
import org.aspectj.weaver.ResolvedTypeX;
import org.aspectj.weaver.TypeX;
+import org.aspectj.weaver.WeaverMessages;
import org.aspectj.weaver.WeaverStateInfo;
import org.aspectj.weaver.World;
import org.aspectj.weaver.bcel.LazyClassGen;
+import org.aspectj.weaver.patterns.DeclareAnnotation;
import org.aspectj.weaver.patterns.DeclareParents;
/**
Collection typeMungers = factory.getTypeMungers();
Collection declareParents = factory.getDeclareParents();
+ Collection declareAnnotationOnTypes = factory.getDeclareAnnotationOnTypes();
doPendingWeaves();
// we had the full list.
//
// but these aren't common cases (he bravely said...)
- boolean typeProcessingOrderIsImportant = declareParents.size()>0;
+ boolean typeProcessingOrderIsImportant = declareParents.size()>0 || declareAnnotationOnTypes.size()>0; //DECAT
if (typeProcessingOrderIsImportant) {
List typesToProcess = new ArrayList();
while (typesToProcess.size()>0) {
// A side effect of weaveIntertypes() is that the processed type is removed from the collection
- weaveIntertypes(typesToProcess,(SourceTypeBinding)typesToProcess.get(0),typeMungers,declareParents);
+ weaveIntertypes(typesToProcess,(SourceTypeBinding)typesToProcess.get(0),typeMungers,declareParents,declareAnnotationOnTypes);
}
} else {
// Order isn't important
for (int i = lastCompletedUnitIndex + 1; i <= lastUnitIndex; i++) {
//System.err.println("Working on "+new String(units[i].getFileName()));
- weaveInterTypeDeclarations(units[i].scope, typeMungers, declareParents);
+ weaveInterTypeDeclarations(units[i].scope, typeMungers, declareParents,declareAnnotationOnTypes);
}
}
* if you supply 'pieces' of a hierarchy, i.e. the bottom and the top, but not the middle - but what the hell
* are you doing if you do that?
*/
- private void weaveIntertypes(List typesToProcess,SourceTypeBinding typeToWeave,Collection typeMungers,Collection declareParents) {
+ private void weaveIntertypes(List typesToProcess,SourceTypeBinding typeToWeave,Collection typeMungers,
+ Collection declareParents,Collection declareAnnotationOnTypes) {
// Look at the supertype first
ReferenceBinding superType = typeToWeave.superclass();
- //System.err.println("Been asked to weave "+new String(typeToWeave.getFileName()));
if (typesToProcess.contains(superType) && superType instanceof SourceTypeBinding) {
//System.err.println("Recursing to supertype "+new String(superType.getFileName()));
- weaveIntertypes(typesToProcess,(SourceTypeBinding)superType,typeMungers,declareParents);
+ weaveIntertypes(typesToProcess,(SourceTypeBinding)superType,typeMungers,declareParents,declareAnnotationOnTypes);
}
// Then look at the superinterface list
ReferenceBinding[] interfaceTypes = typeToWeave.superInterfaces();
ReferenceBinding binding = interfaceTypes[i];
if (typesToProcess.contains(binding) && binding instanceof SourceTypeBinding) {
//System.err.println("Recursing to superinterface "+new String(binding.getFileName()));
- weaveIntertypes(typesToProcess,(SourceTypeBinding)binding,typeMungers,declareParents);
+ weaveIntertypes(typesToProcess,(SourceTypeBinding)binding,typeMungers,declareParents,declareAnnotationOnTypes);
}
}
- weaveInterTypeDeclarations(typeToWeave,typeMungers,declareParents,false);
+ weaveInterTypeDeclarations(typeToWeave,typeMungers,declareParents,declareAnnotationOnTypes,false);
typesToProcess.remove(typeToWeave);
}
}
}
- private void weaveInterTypeDeclarations(CompilationUnitScope unit, Collection typeMungers, Collection declareParents) {
+ private void weaveInterTypeDeclarations(CompilationUnitScope unit, Collection typeMungers,
+ Collection declareParents, Collection declareAnnotationOnTypes) {
for (int i = 0, length = unit.topLevelTypes.length; i < length; i++) {
- weaveInterTypeDeclarations(unit.topLevelTypes[i], typeMungers, declareParents, false);
+ weaveInterTypeDeclarations(unit.topLevelTypes[i], typeMungers, declareParents, declareAnnotationOnTypes,false);
}
}
if (!factory.areTypeMungersFinished()) {
if (!pendingTypesToWeave.contains(sourceType)) pendingTypesToWeave.add(sourceType);
} else {
- weaveInterTypeDeclarations(sourceType, factory.getTypeMungers(), factory.getDeclareParents(), true);
+ weaveInterTypeDeclarations(sourceType, factory.getTypeMungers(), factory.getDeclareParents(), factory.getDeclareAnnotationOnTypes(),true);
}
}
- private void weaveInterTypeDeclarations(SourceTypeBinding sourceType, Collection typeMungers, Collection declareParents, boolean skipInners) {
+ private void weaveInterTypeDeclarations(SourceTypeBinding sourceType, Collection typeMungers,
+ Collection declareParents, Collection declareAnnotationOnTypes, boolean skipInners) {
ResolvedTypeX onType = factory.fromEclipse(sourceType);
WeaverStateInfo info = onType.getWeaverState();
onType.clearInterTypeMungers();
+ // FIXME asc perf Could optimize here, after processing the expected set of types we may bring
+ // binary types that are not exposed to the weaver, there is no need to attempt declare parents
+ // or declare annotation really - unless we want to report the not-exposed to weaver
+ // messages...
+
+ List decpToRepeat = new ArrayList();
+ List decaToRepeat = new ArrayList();
+ boolean anyNewParents = false;
+ boolean anyNewAnnotations = false;
+
+ // first pass
+ // try and apply all decps - if they match, then great. If they don't then
+ // check if they are starred-annotation patterns. If they are not starred
+ // annotation patterns then they might match later...remember that...
for (Iterator i = declareParents.iterator(); i.hasNext();) {
- doDeclareParents((DeclareParents)i.next(), sourceType);
+ DeclareParents decp = (DeclareParents)i.next();
+ boolean didSomething = doDeclareParents(decp, sourceType);
+ if (didSomething) {
+ anyNewParents = true;
+ } else {
+ if (!decp.getChild().isStarAnnotation()) decpToRepeat.add(decp);
+ }
+ }
+
+ for (Iterator i = declareAnnotationOnTypes.iterator(); i.hasNext();) {
+ DeclareAnnotation deca = (DeclareAnnotation)i.next();
+ boolean didSomething = doDeclareAnnotations(deca, sourceType,true);
+ if (didSomething) {
+ anyNewAnnotations = true;
+ } else {
+ if (!deca.getTypePattern().isStar()) decaToRepeat.add(deca);
+ }
+ }
+
+ // now lets loop over and over until we have done all we can
+ while ((anyNewAnnotations || anyNewParents) &&
+ (!decpToRepeat.isEmpty() || !decaToRepeat.isEmpty())) {
+ anyNewParents = anyNewAnnotations = false;
+ List forRemoval = new ArrayList();
+ for (Iterator i = decpToRepeat.iterator(); i.hasNext();) {
+ DeclareParents decp = (DeclareParents)i.next();
+ boolean didSomething = doDeclareParents(decp, sourceType);
+ if (didSomething) {
+ anyNewParents = true;
+ forRemoval.add(decp);
+ }
+ }
+ decpToRepeat.removeAll(forRemoval);
+
+ forRemoval = new ArrayList();
+ for (Iterator i = declareAnnotationOnTypes.iterator(); i.hasNext();) {
+ DeclareAnnotation deca = (DeclareAnnotation)i.next();
+ boolean didSomething = doDeclareAnnotations(deca, sourceType,false);
+ if (didSomething) {
+ anyNewAnnotations = true;
+ forRemoval.add(deca);
+ }
+ }
+ decaToRepeat.removeAll(forRemoval);
}
+
for (Iterator i = typeMungers.iterator(); i.hasNext();) {
EclipseTypeMunger munger = (EclipseTypeMunger) i.next();
if (munger.matches(onType)) {
}
}
+
//???onType.checkInterTypeMungers();
onType.checkInterTypeMungers();
for (Iterator i = onType.getInterTypeMungers().iterator(); i.hasNext();) {
munger.munge(sourceType);
}
+ // Call if you would like to do source weaving of declare @method/@constructor
+ // at source time... no need to do this as it can't impact anything, but left here for
+ // future generations to enjoy. Method source is commented out at the end of this module
+ // doDeclareAnnotationOnMethods();
+
+ // Call if you would like to do source weaving of declare @field
+ // at source time... no need to do this as it can't impact anything, but left here for
+ // future generations to enjoy. Method source is commented out at the end of this module
+ // doDeclareAnnotationOnFields();
+
if (skipInners) return;
ReferenceBinding[] memberTypes = sourceType.memberTypes;
for (int i = 0, length = memberTypes.length; i < length; i++) {
if (memberTypes[i] instanceof SourceTypeBinding) {
- weaveInterTypeDeclarations((SourceTypeBinding) memberTypes[i], typeMungers, declareParents, false);
+ weaveInterTypeDeclarations((SourceTypeBinding) memberTypes[i], typeMungers, declareParents,declareAnnotationOnTypes, false);
}
}
}
- private void doDeclareParents(DeclareParents declareParents, SourceTypeBinding sourceType) {
+ private boolean doDeclareParents(DeclareParents declareParents, SourceTypeBinding sourceType) {
List newParents = declareParents.findMatchingNewParents(factory.fromEclipse(sourceType),false);
if (!newParents.isEmpty()) {
for (Iterator i = newParents.iterator(); i.hasNext(); ) {
AsmRelationshipProvider.getDefault().addDeclareParentsRelationship(declareParents.getSourceLocation(),factory.fromEclipse(sourceType), newParents);
addParent(sourceType, parent);
}
+ return true;
+ }
+ return false;
+ }
+
+ private String stringifyTargets(long bits) {
+ if ((bits & TagBits.AnnotationTargetMASK)==0) return "";
+ Set s = new HashSet();
+ if ((bits&TagBits.AnnotationForAnnotationType)!=0) s.add("ANNOTATION_TYPE");
+ if ((bits&TagBits.AnnotationForConstructor)!=0) s.add("CONSTRUCTOR");
+ if ((bits&TagBits.AnnotationForField)!=0) s.add("FIELD");
+ if ((bits&TagBits.AnnotationForLocalVariable)!=0) s.add("LOCAL_VARIABLE");
+ if ((bits&TagBits.AnnotationForMethod)!=0) s.add("METHOD");
+ if ((bits&TagBits.AnnotationForPackage)!=0) s.add("PACKAGE");
+ if ((bits&TagBits.AnnotationForParameter)!=0) s.add("PARAMETER");
+ if ((bits&TagBits.AnnotationForType)!=0) s.add("TYPE");
+ StringBuffer sb = new StringBuffer();
+ sb.append("{");
+ for (Iterator iter = s.iterator(); iter.hasNext();) {
+ String element = (String) iter.next();
+ sb.append(element);
+ if (iter.hasNext()) sb.append(",");
+ }
+ sb.append("}");
+ return sb.toString();
+ }
+
+ private boolean doDeclareAnnotations(DeclareAnnotation decA, SourceTypeBinding sourceType,boolean reportProblems) {
+ ResolvedTypeX rtx = factory.fromEclipse(sourceType);
+ if (!decA.matches(rtx)) return false;
+ if (!rtx.isExposedToWeaver()) return false;
+
+
+ // Get the annotation specified in the declare
+ TypeBinding tb = factory.makeTypeBinding(decA.getAspect());
+ MethodBinding[] mbs = ((SourceTypeBinding)tb).getMethods(decA.getAnnotationMethod().toCharArray());
+ long abits = mbs[0].getAnnotationTagBits(); // ensure resolved
+ TypeDeclaration typeDecl = ((SourceTypeBinding)mbs[0].declaringClass).scope.referenceContext;
+ AbstractMethodDeclaration methodDecl = typeDecl.declarationOf(mbs[0]);
+ Annotation[] toAdd = methodDecl.annotations; // this is what to add
+ abits = toAdd[0].resolvedType.getAnnotationTagBits();
+
+ Annotation currentAnnotations[] = sourceType.scope.referenceContext.annotations;
+ if (currentAnnotations!=null)
+ for (int i = 0; i < currentAnnotations.length; i++) {
+ Annotation annotation = currentAnnotations[i];
+ String a = CharOperation.toString(annotation.type.getTypeName());
+ String b = CharOperation.toString(toAdd[0].type.getTypeName());
+ // FIXME asc we have a lint for attempting to add an annotation twice to a method,
+ // we could put it out here *if* we can resolve the problem of errors coming out
+ // multiple times if we have cause to loop through here
+ if (a.equals(b)) return false;
+ }
+
+ if (((abits & TagBits.AnnotationTargetMASK)!=0)) {
+ if ( (abits & (TagBits.AnnotationForAnnotationType | TagBits.AnnotationForType))==0) {
+ // this means it specifies something other than annotation or normal type - error will have been already reported, just resolution process above
+ return false;
+ }
+ if ( (sourceType.isAnnotationType() && (abits & TagBits.AnnotationForAnnotationType)==0) ||
+ (!sourceType.isAnnotationType() && (abits & TagBits.AnnotationForType)==0) ) {
+
+ if (reportProblems) {
+ if (decA.isExactPattern()) {
+ factory.showMessage(IMessage.ERROR,
+ WeaverMessages.format(WeaverMessages.INCORRECT_TARGET_FOR_DECLARE_ANNOTATION,rtx.getName(),toAdd[0].type,stringifyTargets(abits)),
+ decA.getSourceLocation(), null);
+ }
+ // dont put out the lint - the weaving process will do that
+// else {
+// if (factory.getWorld().getLint().invalidTargetForAnnotation.isEnabled()) {
+// factory.getWorld().getLint().invalidTargetForAnnotation.signal(new String[]{rtx.getName(),toAdd[0].type.toString(),stringifyTargets(abits)},decA.getSourceLocation(),null);
+// }
+// }
+ }
+ return false;
+ }
}
+
+ // Build a new array of annotations
+ // FIXME asc Should be caching the old set of annotations in the type so the class file
+ // generated doesn't have the annotation, it will then be added again during
+ // binary weaving? (similar to declare parents handling...)
+ AsmRelationshipProvider.getDefault().addDeclareAnnotationRelationship(decA.getSourceLocation(),rtx.getSourceLocation());
+ Annotation abefore[] = sourceType.scope.referenceContext.annotations;
+ Annotation[] newset = new Annotation[toAdd.length+(abefore==null?0:abefore.length)];
+ System.arraycopy(toAdd,0,newset,0,toAdd.length);
+ if (abefore!=null) {
+ System.arraycopy(abefore,0,newset,toAdd.length,abefore.length);
+ }
+ sourceType.scope.referenceContext.annotations = newset;
+ return true;
}
+
private void reportDeclareParentsMessage(WeaveMessage.WeaveMessageKind wmk,SourceTypeBinding sourceType,ResolvedTypeX parent) {
if (!factory.getWorld().getMessageHandler().isIgnoring(IMessage.WEAVEINFO)) {
}
}
}
+
+// commented out, supplied as info on how to manipulate annotations in an eclipse world
+//
+// public void doDeclareAnnotationOnMethods() {
+// Do the declare annotation on fields/methods/ctors
+//Collection daoms = factory.getDeclareAnnotationOnMethods();
+//if (daoms!=null && daoms.size()>0 && !(sourceType instanceof BinaryTypeBinding)) {
+// System.err.println("Going through the methods on "+sourceType.debugName()+" looking for DECA matches");
+// // We better take a look through them...
+// for (Iterator iter = daoms.iterator(); iter.hasNext();) {
+// DeclareAnnotation element = (DeclareAnnotation) iter.next();
+// System.err.println("Looking for anything that might match "+element+" on "+sourceType.debugName()+" "+getType(sourceType.compoundName).debugName()+" "+(sourceType instanceof BinaryTypeBinding));
+//
+// ReferenceBinding rbb = getType(sourceType.compoundName);
+// // fix me if we ever uncomment this code... should iterate the other way round, over the methods then over the decas
+// sourceType.methods();
+// MethodBinding sourceMbs[] = sourceType.methods;
+// for (int i = 0; i < sourceMbs.length; i++) {
+// MethodBinding sourceMb = sourceMbs[i];
+// MethodBinding mbbbb = ((SourceTypeBinding)rbb).getExactMethod(sourceMb.selector,sourceMb.parameters);
+// boolean isCtor = sourceMb.selector[0]=='<';
+//
+// if ((element.isDeclareAtConstuctor() ^ !isCtor)) {
+// System.err.println("Checking "+sourceMb+" ... declaringclass="+sourceMb.declaringClass.debugName()+" rbb="+rbb.debugName()+" "+sourceMb.declaringClass.equals(rbb));
+//
+// ResolvedMember rm = null;
+// rm = EclipseFactory.makeResolvedMember(mbbbb);
+// if (element.matches(rm,factory.getWorld())) {
+// System.err.println("MATCH");
+//
+// // Determine the set of annotations that are currently on the method
+// ReferenceBinding rb = getType(sourceType.compoundName);
+//// TypeBinding tb = factory.makeTypeBinding(decA.getAspect());
+// MethodBinding mb = ((SourceTypeBinding)rb).getExactMethod(sourceMb.selector,sourceMb.parameters);
+// //long abits = mbs[0].getAnnotationTagBits(); // ensure resolved
+// TypeDeclaration typeDecl = ((SourceTypeBinding)sourceMb.declaringClass).scope.referenceContext;
+// AbstractMethodDeclaration methodDecl = typeDecl.declarationOf(sourceMb);
+// Annotation[] currentlyHas = methodDecl.annotations; // this is what to add
+// //abits = toAdd[0].resolvedType.getAnnotationTagBits();
+//
+// // Determine the annotations to add to that method
+// TypeBinding tb = factory.makeTypeBinding(element.getAspect());
+// MethodBinding[] aspectMbs = ((SourceTypeBinding)tb).getMethods(element.getAnnotationMethod().toCharArray());
+// long abits = aspectMbs[0].getAnnotationTagBits(); // ensure resolved
+// TypeDeclaration typeDecl2 = ((SourceTypeBinding)aspectMbs[0].declaringClass).scope.referenceContext;
+// AbstractMethodDeclaration methodDecl2 = typeDecl2.declarationOf(aspectMbs[0]);
+// Annotation[] toAdd = methodDecl2.annotations; // this is what to add
+// // abits = toAdd[0].resolvedType.getAnnotationTagBits();
+//System.err.println("Has: "+currentlyHas+" toAdd: "+toAdd);
+//
+// // fix me? should check if it already has the annotation
+// //Annotation abefore[] = sourceType.scope.referenceContext.annotations;
+// Annotation[] newset = new Annotation[(currentlyHas==null?0:currentlyHas.length)+1];
+// System.arraycopy(toAdd,0,newset,0,toAdd.length);
+// if (currentlyHas!=null) {
+// System.arraycopy(currentlyHas,0,newset,1,currentlyHas.length);
+// }
+// methodDecl.annotations = newset;
+// System.err.println("New set on "+CharOperation.charToString(sourceMb.selector)+" is "+newset);
+// } else
+// System.err.println("NO MATCH");
+// }
+// }
+// }
+//}
+//}
+
+// commented out, supplied as info on how to manipulate annotations in an eclipse world
+//
+// public void doDeclareAnnotationOnFields() {
+// Collection daofs = factory.getDeclareAnnotationOnFields();
+// if (daofs!=null && daofs.size()>0 && !(sourceType instanceof BinaryTypeBinding)) {
+// System.err.println("Going through the fields on "+sourceType.debugName()+" looking for DECA matches");
+// // We better take a look through them...
+// for (Iterator iter = daofs.iterator(); iter.hasNext();) {
+// DeclareAnnotation element = (DeclareAnnotation) iter.next();
+// System.err.println("Processing deca "+element+" on "+sourceType.debugName()+" "+getType(sourceType.compoundName).debugName()+" "+(sourceType instanceof BinaryTypeBinding));
+//
+// ReferenceBinding rbb = getType(sourceType.compoundName);
+// // fix me? should iterate the other way round, over the methods then over the decas
+// sourceType.fields(); // resolve the bloody things
+// FieldBinding sourceFbs[] = sourceType.fields;
+// for (int i = 0; i < sourceFbs.length; i++) {
+// FieldBinding sourceFb = sourceFbs[i];
+// //FieldBinding fbbbb = ((SourceTypeBinding)rbb).getgetExactMethod(sourceMb.selector,sourceMb.parameters);
+//
+// System.err.println("Checking "+sourceFb+" ... declaringclass="+sourceFb.declaringClass.debugName()+" rbb="+rbb.debugName());
+//
+// ResolvedMember rm = null;
+// rm = EclipseFactory.makeResolvedMember(sourceFb);
+// if (element.matches(rm,factory.getWorld())) {
+// System.err.println("MATCH");
+//
+// // Determine the set of annotations that are currently on the field
+// ReferenceBinding rb = getType(sourceType.compoundName);
+//// TypeBinding tb = factory.makeTypeBinding(decA.getAspect());
+// FieldBinding fb = ((SourceTypeBinding)rb).getField(sourceFb.name,true);
+// //long abits = mbs[0].getAnnotationTagBits(); // ensure resolved
+// TypeDeclaration typeDecl = ((SourceTypeBinding)sourceFb.declaringClass).scope.referenceContext;
+// FieldDeclaration fd = typeDecl.declarationOf(sourceFb);
+// //AbstractMethodDeclaration methodDecl = typeDecl.declarationOf(sourceMb);
+// Annotation[] currentlyHas = fd.annotations; // this is what to add
+// //abits = toAdd[0].resolvedType.getAnnotationTagBits();
+//
+// // Determine the annotations to add to that method
+// TypeBinding tb = factory.makeTypeBinding(element.getAspect());
+// MethodBinding[] aspectMbs = ((SourceTypeBinding)tb).getMethods(element.getAnnotationMethod().toCharArray());
+// long abits = aspectMbs[0].getAnnotationTagBits(); // ensure resolved
+// TypeDeclaration typeDecl2 = ((SourceTypeBinding)aspectMbs[0].declaringClass).scope.referenceContext;
+// AbstractMethodDeclaration methodDecl2 = typeDecl2.declarationOf(aspectMbs[0]);
+// Annotation[] toAdd = methodDecl2.annotations; // this is what to add
+// // abits = toAdd[0].resolvedType.getAnnotationTagBits();
+//System.err.println("Has: "+currentlyHas+" toAdd: "+toAdd);
+//
+// // fix me? check if it already has the annotation
+//
+//
+// //Annotation abefore[] = sourceType.scope.referenceContext.annotations;
+// Annotation[] newset = new Annotation[(currentlyHas==null?0:currentlyHas.length)+1];
+// System.arraycopy(toAdd,0,newset,0,toAdd.length);
+// if (currentlyHas!=null) {
+// System.arraycopy(currentlyHas,0,newset,1,currentlyHas.length);
+// }
+// fd.annotations = newset;
+// System.err.println("New set on "+CharOperation.charToString(sourceFb.name)+" is "+newset);
+// } else
+// System.err.println("NO MATCH");
+// }
+//
+// }
+// }