1121
1122
* will iterate over the fields repeatedly until everything has been applied.
1124
private boolean weaveAtFieldRepeatedly(List<DeclareAnnotation> decaFs, List itdFields, List<Integer> reportedErrors) {
1125
private boolean weaveAtFieldRepeatedly(List<DeclareAnnotation> decaFs, List<ConcreteTypeMunger> itdFields,
1126
List<Integer> reportedErrors) {
1125
1127
boolean isChanged = false;
1126
for (Iterator iter = itdFields.iterator(); iter.hasNext();) {
1128
for (Iterator<ConcreteTypeMunger> iter = itdFields.iterator(); iter.hasNext();) {
1127
1129
BcelTypeMunger fieldMunger = (BcelTypeMunger) iter.next();
1128
1130
ResolvedMember itdIsActually = fieldMunger.getSignature();
1129
List<DeclareAnnotation> worthRetrying = new ArrayList<DeclareAnnotation>();
1131
Set<DeclareAnnotation> worthRetrying = new LinkedHashSet<DeclareAnnotation>();
1130
1132
boolean modificationOccured = false;
1132
1134
for (Iterator<DeclareAnnotation> iter2 = decaFs.iterator(); iter2.hasNext();) {
1133
1135
DeclareAnnotation decaF = iter2.next();
1135
1136
if (decaF.matches(itdIsActually, world)) {
1136
LazyMethodGen annotationHolder = locateAnnotationHolderForFieldMunger(clazz, fieldMunger);
1137
if (doesAlreadyHaveAnnotation(annotationHolder, itdIsActually, decaF, reportedErrors)) {
1138
continue; // skip this one...
1137
if (decaF.isRemover()) {
1138
LazyMethodGen annotationHolder = locateAnnotationHolderForFieldMunger(clazz, fieldMunger);
1139
if (annotationHolder.hasAnnotation(decaF.getAnnotationType())) {
1141
// something to remove
1142
annotationHolder.removeAnnotation(decaF.getAnnotationType());
1143
AsmRelationshipProvider.addDeclareAnnotationRelationship(world.getModelAsAsmManager(),
1144
decaF.getSourceLocation(), itdIsActually.getSourceLocation(), true);
1146
worthRetrying.add(decaF);
1150
LazyMethodGen annotationHolder = locateAnnotationHolderForFieldMunger(clazz, fieldMunger);
1151
if (doesAlreadyHaveAnnotation(annotationHolder, itdIsActually, decaF, reportedErrors)) {
1152
continue; // skip this one...
1154
annotationHolder.addAnnotation(decaF.getAnnotation());
1155
AsmRelationshipProvider.addDeclareAnnotationRelationship(world.getModelAsAsmManager(),
1156
decaF.getSourceLocation(), itdIsActually.getSourceLocation(), false);
1158
modificationOccured = true;
1140
annotationHolder.addAnnotation(decaF.getAnnotation());
1141
AsmRelationshipProvider.addDeclareAnnotationRelationship(world.getModelAsAsmManager(), decaF
1142
.getSourceLocation(), itdIsActually.getSourceLocation());
1144
modificationOccured = true;
1147
1161
if (!decaF.isStarredAnnotationPattern()) {
1148
1162
worthRetrying.add(decaF); // an annotation is specified
1158
1172
for (Iterator<DeclareAnnotation> iter2 = worthRetrying.iterator(); iter2.hasNext();) {
1159
1173
DeclareAnnotation decaF = iter2.next();
1160
1174
if (decaF.matches(itdIsActually, world)) {
1161
LazyMethodGen annotationHolder = locateAnnotationHolderForFieldMunger(clazz, fieldMunger);
1162
if (doesAlreadyHaveAnnotation(annotationHolder, itdIsActually, decaF, reportedErrors)) {
1163
continue; // skip this one...
1175
if (decaF.isRemover()) {
1176
LazyMethodGen annotationHolder = locateAnnotationHolderForFieldMunger(clazz, fieldMunger);
1177
if (annotationHolder.hasAnnotation(decaF.getAnnotationType())) {
1179
// something to remove
1180
annotationHolder.removeAnnotation(decaF.getAnnotationType());
1181
AsmRelationshipProvider.addDeclareAnnotationRelationship(world.getModelAsAsmManager(),
1182
decaF.getSourceLocation(), itdIsActually.getSourceLocation(), true);
1183
forRemoval.add(decaF);
1186
LazyMethodGen annotationHolder = locateAnnotationHolderForFieldMunger(clazz, fieldMunger);
1187
if (doesAlreadyHaveAnnotation(annotationHolder, itdIsActually, decaF, reportedErrors)) {
1188
continue; // skip this one...
1190
annotationHolder.addAnnotation(decaF.getAnnotation());
1191
AsmRelationshipProvider.addDeclareAnnotationRelationship(world.getModelAsAsmManager(),
1192
decaF.getSourceLocation(), itdIsActually.getSourceLocation(), false);
1194
modificationOccured = true;
1195
forRemoval.add(decaF);
1165
annotationHolder.addAnnotation(decaF.getAnnotation());
1166
AsmRelationshipProvider.addDeclareAnnotationRelationship(world.getModelAsAsmManager(), decaF
1167
.getSourceLocation(), itdIsActually.getSourceLocation());
1169
modificationOccured = true;
1170
forRemoval.add(decaF);
1173
1199
worthRetrying.removeAll(forRemoval);
1259
1287
* as well as on the interfieldinit method.
1261
1289
private boolean weaveDeclareAtField(LazyClassGen clazz) {
1263
// BUGWARNING not getting enough warnings out on declare @field ?
1264
// There is a potential problem here with warnings not coming out - this
1265
// will occur if they are created on the second iteration round this
1267
// We currently deactivate error reporting for the second time round.
1268
// A possible solution is to record what annotations were added by what
1269
// decafs and check that to see if an error needs to be reported - this
1270
// would be expensive so lets skip it for now
1272
1290
List<Integer> reportedProblems = new ArrayList<Integer>();
1274
1291
List<DeclareAnnotation> allDecafs = world.getDeclareAnnotationOnFields();
1275
1292
if (allDecafs.isEmpty()) {
1279
boolean isChanged = false;
1280
List<ConcreteTypeMunger> itdFields = getITDSubset(clazz, ResolvedTypeMunger.Field);
1281
if (itdFields != null) {
1282
isChanged = weaveAtFieldRepeatedly(allDecafs, itdFields, reportedProblems);
1285
List<DeclareAnnotation> decaFs = getMatchingSubset(allDecafs, clazz.getType());
1286
if (decaFs.isEmpty()) {
1287
return false; // nothing more to do
1295
boolean typeIsChanged = false;
1296
List<ConcreteTypeMunger> relevantItdFields = getITDSubset(clazz, ResolvedTypeMunger.Field);
1297
if (relevantItdFields != null) {
1298
typeIsChanged = weaveAtFieldRepeatedly(allDecafs, relevantItdFields, reportedProblems);
1301
List<DeclareAnnotation> decafs = getMatchingSubset(allDecafs, clazz.getType());
1302
if (decafs.isEmpty()) {
1303
return typeIsChanged;
1289
1306
List<BcelField> fields = clazz.getFieldGens();
1290
1307
if (fields != null) {
1291
1308
Set<DeclareAnnotation> unusedDecafs = new HashSet<DeclareAnnotation>();
1292
unusedDecafs.addAll(decaFs);
1293
for (int fieldCounter = 0; fieldCounter < fields.size(); fieldCounter++) {
1294
BcelField aBcelField = fields.get(fieldCounter);// new
1295
// BcelField(clazz.getBcelObjectType(),fields[fieldCounter
1297
if (!aBcelField.getName().startsWith(NameMangler.PREFIX)) {
1309
unusedDecafs.addAll(decafs);
1310
for (BcelField field : fields) {
1311
if (!field.getName().startsWith(NameMangler.PREFIX)) {
1298
1312
// Single first pass
1299
List<DeclareAnnotation> worthRetrying = new ArrayList<DeclareAnnotation>();
1313
Set<DeclareAnnotation> worthRetrying = new LinkedHashSet<DeclareAnnotation>();
1300
1314
boolean modificationOccured = false;
1302
AnnotationAJ[] dontAddMeTwice = aBcelField.getAnnotations();
1315
AnnotationAJ[] dontAddMeTwice = field.getAnnotations();
1304
1317
// go through all the declare @field statements
1305
for (DeclareAnnotation decaF : decaFs) {
1306
if (decaF.getAnnotation() == null) {
1318
for (DeclareAnnotation decaf : decafs) {
1319
if (decaf.getAnnotation() == null) {
1309
if (decaF.matches(aBcelField, world)) {
1311
if (!dontAddTwice(decaF, dontAddMeTwice)) {
1312
if (doesAlreadyHaveAnnotation(aBcelField, decaF, reportedProblems)) {
1313
// remove the declare @field since don't
1314
// want an error when
1315
// the annotation is already there
1316
unusedDecafs.remove(decaF);
1320
if (decaF.getAnnotation().isRuntimeVisible()) { // isAnnotationWithRuntimeRetention
1324
// getJavaClass(world))){
1325
// if(decaF.getAnnotationTypeX().
1326
// isAnnotationWithRuntimeRetention(world)){
1327
// it should be runtime visible, so put it
1330
// decaF.getAnnotationX().getBcelAnnotation
1332
// AnnotationGen ag = new
1333
// AnnotationGen(a,clazz
1334
// .getConstantPoolGen(),true);
1335
// FieldGen myGen = new
1336
// FieldGen(fields[fieldCounter
1337
// ],clazz.getConstantPoolGen());
1338
// myGen.addAnnotation(ag);
1339
// Field newField = myGen.getField();
1341
aBcelField.addAnnotation(decaF.getAnnotation());
1342
// clazz.replaceField(fields[fieldCounter],
1344
// fields[fieldCounter]=newField;
1322
if (decaf.matches(field, world)) {
1323
if (decaf.isRemover()) {
1324
AnnotationAJ annotation = decaf.getAnnotation();
1325
if (field.hasAnnotation(annotation.getType())) {
1326
// something to remove
1327
typeIsChanged = true;
1328
field.removeAnnotation(annotation);
1329
AsmRelationshipProvider.addDeclareAnnotationFieldRelationship(world.getModelAsAsmManager(),
1330
decaf.getSourceLocation(), clazz.getName(), field, true);
1331
reportFieldAnnotationWeavingMessage(clazz, field, decaf, true);
1347
aBcelField.addAnnotation(decaF.getAnnotation());
1351
AsmRelationshipProvider.addDeclareAnnotationFieldRelationship(world.getModelAsAsmManager(), decaF
1352
.getSourceLocation(), clazz.getName(), aBcelField);
1353
reportFieldAnnotationWeavingMessage(clazz, fields, fieldCounter, decaF);
1355
modificationOccured = true;
1356
// remove the declare @field since have matched
1358
unusedDecafs.remove(decaF);
1360
if (!decaF.isStarredAnnotationPattern()) {
1361
worthRetrying.add(decaF); // an annotation is
1333
worthRetrying.add(decaf);
1335
unusedDecafs.remove(decaf);
1337
if (!dontAddTwice(decaf, dontAddMeTwice)) {
1338
if (doesAlreadyHaveAnnotation(field, decaf, reportedProblems)) {
1339
// remove the declare @field since don't want an error when the annotation is already there
1340
unusedDecafs.remove(decaf);
1343
field.addAnnotation(decaf.getAnnotation());
1345
AsmRelationshipProvider.addDeclareAnnotationFieldRelationship(world.getModelAsAsmManager(),
1346
decaf.getSourceLocation(), clazz.getName(), field, false);
1347
reportFieldAnnotationWeavingMessage(clazz, field, decaf, false);
1348
typeIsChanged = true;
1349
modificationOccured = true;
1350
unusedDecafs.remove(decaf);
1352
} else if (!decaf.isStarredAnnotationPattern() || decaf.isRemover()) {
1353
worthRetrying.add(decaf); // an annotation is specified that might be put on by a subsequent decaf
1370
1357
// Multiple secondary passes
1371
1358
while (!worthRetrying.isEmpty() && modificationOccured) {
1372
1359
modificationOccured = false;
1373
// lets have another go
1360
// lets have another go with any remaining ones
1374
1361
List<DeclareAnnotation> forRemoval = new ArrayList<DeclareAnnotation>();
1375
1362
for (Iterator<DeclareAnnotation> iter = worthRetrying.iterator(); iter.hasNext();) {
1376
1363
DeclareAnnotation decaF = iter.next();
1377
if (decaF.matches(aBcelField, world)) {
1378
// below code is for recursive things
1379
if (doesAlreadyHaveAnnotation(aBcelField, decaF, reportedProblems)) {
1380
// remove the declare @field since don't
1381
// want an error when
1382
// the annotation is already there
1365
if (decaF.matches(field, world)) {
1366
if (decaF.isRemover()) {
1367
AnnotationAJ annotation = decaF.getAnnotation();
1368
if (field.hasAnnotation(annotation.getType())) {
1369
// something to remove
1370
typeIsChanged = modificationOccured = true;
1371
forRemoval.add(decaF);
1372
field.removeAnnotation(annotation);
1373
AsmRelationshipProvider.addDeclareAnnotationFieldRelationship(world.getModelAsAsmManager(),
1374
decaF.getSourceLocation(), clazz.getName(), field, true);
1375
reportFieldAnnotationWeavingMessage(clazz, field, decaF, true);
1378
// below code is for recursive things
1383
1379
unusedDecafs.remove(decaF);
1384
continue; // skip this one...
1380
if (doesAlreadyHaveAnnotation(field, decaF, reportedProblems)) {
1383
field.addAnnotation(decaF.getAnnotation());
1384
AsmRelationshipProvider.addDeclareAnnotationFieldRelationship(world.getModelAsAsmManager(),
1385
decaF.getSourceLocation(), clazz.getName(), field, false);
1386
typeIsChanged = modificationOccured = true;
1387
forRemoval.add(decaF);
1386
aBcelField.addAnnotation(decaF.getAnnotation());
1387
AsmRelationshipProvider.addDeclareAnnotationFieldRelationship(world.getModelAsAsmManager(), decaF
1388
.getSourceLocation(), clazz.getName(), aBcelField);
1390
modificationOccured = true;
1391
forRemoval.add(decaF);
1392
// remove the declare @field since have matched
1394
unusedDecafs.remove(decaF);
1397
1391
worthRetrying.removeAll(forRemoval);