135
140
if (changed && worthReporting) {
136
AsmRelationshipProvider.addRelationship(((BcelWorld) getWorld()).getModelAsAsmManager(), weaver.getLazyClassGen()
137
.getType(), munger, getAspectType());
141
ResolvedType declaringAspect = null;
142
AsmManager model = ((BcelWorld) getWorld()).getModelAsAsmManager();
144
if (munger instanceof NewParentTypeMunger) {
145
NewParentTypeMunger nptMunger = (NewParentTypeMunger) munger;
146
declaringAspect = nptMunger.getDeclaringType();
147
if (declaringAspect.isParameterizedOrGenericType()) {
148
declaringAspect = declaringAspect.getRawType();
150
ResolvedType thisAspect = getAspectType();
151
AsmRelationshipProvider.addRelationship(model, weaver.getLazyClassGen().getType(), munger, thisAspect);
153
// Add a relationship on the actual declaring aspect too
154
if (!thisAspect.equals(declaringAspect)) {
155
// Might be the case the declaring aspect is generic and thisAspect is parameterizing it. In that case
156
// record the actual parameterizations
158
ResolvedType target = weaver.getLazyClassGen().getType();
159
ResolvedType newParent = nptMunger.getNewParent();
160
IProgramElement thisAspectNode = model.getHierarchy().findElementForType(thisAspect.getPackageName(),
161
thisAspect.getClassName());
162
Map<String, List<String>> declareParentsMap = thisAspectNode.getDeclareParentsMap();
163
if (declareParentsMap == null) {
164
declareParentsMap = new HashMap<String, List<String>>();
165
thisAspectNode.setDeclareParentsMap(declareParentsMap);
167
String tname = target.getName();
168
String pname = newParent.getName();
169
List<String> newparents = declareParentsMap.get(tname);
170
if (newparents == null) {
171
newparents = new ArrayList<String>();
172
declareParentsMap.put(tname, newparents);
174
newparents.add(pname);
175
AsmRelationshipProvider.addRelationship(model, weaver.getLazyClassGen().getType(), munger, declaringAspect);
178
declaringAspect = getAspectType();
179
AsmRelationshipProvider.addRelationship(model, weaver.getLazyClassGen().getType(), munger, declaringAspect);
140
184
// TAG: WeavingMessage
151
195
// if doing parents munging at compile time only...
152
196
NewParentTypeMunger parentTM = (NewParentTypeMunger) munger;
153
197
if (parentTM.isMixin()) {
154
weaver.getWorld().getMessageHandler().handleMessage(
155
WeaveMessage.constructWeavingMessage(WeaveMessage.WEAVEMESSAGE_MIXIN,
156
new String[] { parentTM.getNewParent().getName(), fName,
157
weaver.getLazyClassGen().getType().getName(), tName }, weaver.getLazyClassGen()
158
.getClassName(), getAspectType().getName()));
201
WeaveMessage.constructWeavingMessage(WeaveMessage.WEAVEMESSAGE_MIXIN, new String[] {
202
parentTM.getNewParent().getName(), fName, weaver.getLazyClassGen().getType().getName(),
203
tName }, weaver.getLazyClassGen().getClassName(), getAspectType().getName()));
160
205
if (parentTM.getNewParent().isInterface()) {
161
weaver.getWorld().getMessageHandler().handleMessage(
162
WeaveMessage.constructWeavingMessage(WeaveMessage.WEAVEMESSAGE_DECLAREPARENTSIMPLEMENTS,
163
new String[] { weaver.getLazyClassGen().getType().getName(), tName,
164
parentTM.getNewParent().getName(), fName },
165
weaver.getLazyClassGen().getClassName(), getAspectType().getName()));
209
WeaveMessage.constructWeavingMessage(WeaveMessage.WEAVEMESSAGE_DECLAREPARENTSIMPLEMENTS,
210
new String[] { weaver.getLazyClassGen().getType().getName(), tName,
211
parentTM.getNewParent().getName(), fName }, weaver.getLazyClassGen()
212
.getClassName(), getAspectType().getName()));
167
weaver.getWorld().getMessageHandler().handleMessage(
168
WeaveMessage.constructWeavingMessage(WeaveMessage.WEAVEMESSAGE_DECLAREPARENTSEXTENDS, new String[] {
169
weaver.getLazyClassGen().getType().getName(), tName, parentTM.getNewParent().getName(),
217
WeaveMessage.constructWeavingMessage(WeaveMessage.WEAVEMESSAGE_DECLAREPARENTSEXTENDS,
218
new String[] { weaver.getLazyClassGen().getType().getName(), tName,
219
parentTM.getNewParent().getName(), fName }));
171
220
// TAG: WeavingMessage DECLARE PARENTS: EXTENDS
172
221
// reportDeclareParentsMessage(WeaveMessage.
173
222
// WEAVEMESSAGE_DECLAREPARENTSEXTENDS,sourceType,parent);
215
266
* For a long time, AspectJ did not allow binary weaving of declare parents. This restriction is now lifted but could do with
218
private boolean mungeNewParent(BcelClassWeaver weaver, NewParentTypeMunger munger) {
269
private boolean mungeNewParent(BcelClassWeaver weaver, NewParentTypeMunger typeTransformer) {
219
270
LazyClassGen newParentTarget = weaver.getLazyClassGen();
220
ResolvedType newParent = munger.getNewParent();
222
boolean cont = true; // Set to false when we error, so we don't actually
224
cont = enforceDecpRule1_abstractMethodsImplemented(weaver, munger.getSourceLocation(), newParentTarget, newParent);
225
cont = enforceDecpRule2_cantExtendFinalClass(weaver, munger.getSourceLocation(), newParentTarget, newParent) && cont;
227
List methods = newParent.getMethodsWithoutIterator(false, true, false);
228
for (Iterator iter = methods.iterator(); iter.hasNext();) {
229
ResolvedMember superMethod = (ResolvedMember) iter.next();
230
if (!superMethod.getName().equals("<init>")) {
231
LazyMethodGen subMethod = findMatchingMethod(newParentTarget, superMethod);
271
ResolvedType newParent = typeTransformer.getNewParent();
273
boolean performChange = true;
274
performChange = enforceDecpRule1_abstractMethodsImplemented(weaver, typeTransformer.getSourceLocation(), newParentTarget,
276
performChange = enforceDecpRule2_cantExtendFinalClass(weaver, typeTransformer.getSourceLocation(), newParentTarget,
277
newParent) && performChange;
279
List<ResolvedMember> methods = newParent.getMethodsWithoutIterator(false, true, false);
280
for (ResolvedMember method : methods) {
281
if (!method.getName().equals("<init>")) {
282
LazyMethodGen subMethod = findMatchingMethod(newParentTarget, method);
232
283
// FIXME asc is this safe for all bridge methods?
233
284
if (subMethod != null && !subMethod.isBridgeMethod()) {
234
if (!(subMethod.isSynthetic() && superMethod.isSynthetic())) {
235
if (!(subMethod.isStatic() && subMethod.getName().startsWith("access$"))) { // ignore generated
237
cont = enforceDecpRule3_visibilityChanges(weaver, newParent, superMethod, subMethod) && cont;
238
cont = enforceDecpRule4_compatibleReturnTypes(weaver, superMethod, subMethod) && cont;
239
cont = enforceDecpRule5_cantChangeFromStaticToNonstatic(weaver, munger.getSourceLocation(),
240
superMethod, subMethod)
285
if (!(subMethod.isSynthetic() && method.isSynthetic())) {
286
if (!(subMethod.isStatic() && subMethod.getName().startsWith("access$"))) {
287
// ignore generated accessors
288
performChange = enforceDecpRule3_visibilityChanges(weaver, newParent, method, subMethod)
290
performChange = enforceDecpRule4_compatibleReturnTypes(weaver, method, subMethod) && performChange;
291
performChange = enforceDecpRule5_cantChangeFromStaticToNonstatic(weaver,
292
typeTransformer.getSourceLocation(), method, subMethod)
248
return false; // A rule was violated and an error message already
299
if (!performChange) {
300
// A rule was violated and an error message already reported
252
if (newParent.isClass()) { // Changing the supertype
304
if (newParent.isClass()) {
305
// Changing the supertype
253
306
if (!attemptToModifySuperCalls(weaver, newParentTarget, newParent)) {
256
309
newParentTarget.setSuperClass(newParent);
257
} else { // Adding a new interface
311
// Add a new interface
258
312
newParentTarget.addInterface(newParent, getSourceLocation());
267
321
private boolean enforceDecpRule1_abstractMethodsImplemented(BcelClassWeaver weaver, ISourceLocation mungerLoc,
268
322
LazyClassGen newParentTarget, ResolvedType newParent) {
323
// Ignore abstract classes or interfaces
324
if (newParentTarget.isAbstract() || newParentTarget.isInterface()) {
269
327
boolean ruleCheckingSucceeded = true;
270
if (!(newParentTarget.isAbstract() || newParentTarget.isInterface())) { // Ignore
275
List methods = newParent.getMethodsWithoutIterator(false, true, false);
276
for (Iterator i = methods.iterator(); i.hasNext();) {
277
ResolvedMember o = (ResolvedMember) i.next();
278
if (o.isAbstract() && !o.getName().startsWith("ajc$interField")) { // Ignore
285
ResolvedMember discoveredImpl = null;
286
List newParentTargetMethods = newParentTarget.getType().getMethodsWithoutIterator(false, true, false);
287
for (Iterator ii = newParentTargetMethods.iterator(); ii.hasNext() && discoveredImpl == null;) {
288
ResolvedMember gen2 = (ResolvedMember) ii.next();
289
if (gen2.getName().equals(o.getName()) && !gen2.isAbstract()) {
290
String oSig = o.getParameterSignature();
292
if (gen2.getParameterSignature().equals(oSig)) {
293
discoveredImpl = gen2;
295
// Does the erasure match? In which case a bridge method will be created later to
296
// satisfy the abstract method
297
if (gen2.hasBackingGenericMember()
298
&& gen2.getBackingGenericMember().getParameterSignature().equals(oSig)) {
299
discoveredImpl = gen2;
304
if (discoveredImpl == null) {
305
// didnt find a valid implementation, lets check the
306
// ITDs on this type to see if they satisfy it
307
boolean satisfiedByITD = false;
308
for (Iterator ii = newParentTarget.getType().getInterTypeMungersIncludingSupers().iterator(); ii.hasNext();) {
309
ConcreteTypeMunger m = (ConcreteTypeMunger) ii.next();
310
if (m.getMunger() != null && m.getMunger().getKind() == ResolvedTypeMunger.Method) {
311
ResolvedMember sig = m.getSignature();
312
if (!Modifier.isAbstract(sig.getModifiers())) {
314
// If the ITD shares a type variable with
315
// some target type, we need to tailor it
318
if (m.isTargetTypeParameterized()) {
319
ResolvedType genericOnType = getWorld().resolve(sig.getDeclaringType()).getGenericType();
320
m = m.parameterizedFor(newParent.discoverActualOccurrenceOfTypeInHierarchy(genericOnType));
321
sig = m.getSignature(); // possible sig
327
if (ResolvedType.matches(AjcMemberMaker.interMethod(sig, m.getAspectType(), sig
328
.getDeclaringType().resolve(weaver.getWorld()).isInterface()), o)) {
329
satisfiedByITD = true;
332
} else if (m.getMunger() != null && m.getMunger().getKind() == ResolvedTypeMunger.MethodDelegate2) {
333
satisfiedByITD = true;// AV - that should be
334
// enough, no need to
338
if (!satisfiedByITD) {
339
error(weaver, "The type " + newParentTarget.getName()
340
+ " must implement the inherited abstract method " + o.getDeclaringType() + "." + o.getName()
341
+ o.getParameterSignature(), newParentTarget.getType().getSourceLocation(),
342
new ISourceLocation[] { o.getSourceLocation(), mungerLoc });
343
ruleCheckingSucceeded = false;
328
List<ResolvedMember> newParentMethods = newParent.getMethodsWithoutIterator(false, true, false);
329
for (ResolvedMember newParentMethod : newParentMethods) {
330
String newParentMethodName = newParentMethod.getName();
331
// Ignore abstract ajc$interField prefixed methods
332
if (newParentMethod.isAbstract() && !newParentMethodName.startsWith("ajc$interField")) {
333
ResolvedMember discoveredImpl = null;
334
List<ResolvedMember> targetMethods = newParentTarget.getType().getMethodsWithoutIterator(false, true, false);
335
for (ResolvedMember targetMethod : targetMethods) {
336
if (!targetMethod.isAbstract() && targetMethod.getName().equals(newParentMethodName)) {
337
String newParentMethodSig = newParentMethod.getParameterSignature(); // ([TT;)
338
String targetMethodSignature = targetMethod.getParameterSignature(); // ([Ljava/lang/Object;)
340
if (targetMethodSignature.equals(newParentMethodSig)) {
341
discoveredImpl = targetMethod;
343
// Does the erasure match? In which case a bridge method will be created later to
344
// satisfy the abstract method
345
if (targetMethod.hasBackingGenericMember()
346
&& targetMethod.getBackingGenericMember().getParameterSignature().equals(newParentMethodSig)) {
347
discoveredImpl = targetMethod;
348
} else if (newParentMethod.hasBackingGenericMember()) {
349
if (newParentMethod.getBackingGenericMember().getParameterSignature().equals(targetMethodSignature)) {
350
discoveredImpl = targetMethod;
354
if (discoveredImpl != null) {
359
if (discoveredImpl == null) {
360
// didnt find a valid implementation, lets check the
361
// ITDs on this type to see if they satisfy it
362
boolean satisfiedByITD = false;
363
for (ConcreteTypeMunger m : newParentTarget.getType().getInterTypeMungersIncludingSupers()) {
364
if (m.getMunger() != null && m.getMunger().getKind() == ResolvedTypeMunger.Method) {
365
ResolvedMember sig = m.getSignature();
366
if (!Modifier.isAbstract(sig.getModifiers())) {
367
// If the ITD shares a type variable with some target type, we need to tailor it
369
if (m.isTargetTypeParameterized()) {
370
ResolvedType genericOnType = getWorld().resolve(sig.getDeclaringType()).getGenericType();
371
m = m.parameterizedFor(newParent.discoverActualOccurrenceOfTypeInHierarchy(genericOnType));
372
// possible sig change when type parameters filled in
373
sig = m.getSignature();
375
if (ResolvedType.matches(
376
AjcMemberMaker.interMethod(sig, m.getAspectType(),
377
sig.getDeclaringType().resolve(weaver.getWorld()).isInterface()), newParentMethod)) {
378
satisfiedByITD = true;
381
} else if (m.getMunger() != null && m.getMunger().getKind() == ResolvedTypeMunger.MethodDelegate2) {
382
// AV - that should be enough, no need to check more
383
satisfiedByITD = true;
386
if (!satisfiedByITD) {
388
"The type " + newParentTarget.getName() + " must implement the inherited abstract method "
389
+ newParentMethod.getDeclaringType() + "." + newParentMethodName
390
+ newParentMethod.getParameterSignature(), newParentTarget.getType().getSourceLocation(),
391
new ISourceLocation[] { newParentMethod.getSourceLocation(), mungerLoc });
392
ruleCheckingSucceeded = false;
370
418
boolean cont = true;
371
419
if (Modifier.isPublic(superMethod.getModifiers())) {
372
420
if (subMethod.isProtected() || subMethod.isDefault() || subMethod.isPrivate()) {
373
weaver.getWorld().getMessageHandler().handleMessage(
374
MessageUtil.error("Cannot reduce the visibility of the inherited method '" + superMethod + "' from "
375
+ newParent.getName(), superMethod.getSourceLocation()));
424
MessageUtil.error("Cannot reduce the visibility of the inherited method '" + superMethod
425
+ "' from " + newParent.getName(), superMethod.getSourceLocation()));
378
428
} else if (Modifier.isProtected(superMethod.getModifiers())) {
379
429
if (subMethod.isDefault() || subMethod.isPrivate()) {
380
weaver.getWorld().getMessageHandler().handleMessage(
381
MessageUtil.error("Cannot reduce the visibility of the inherited method '" + superMethod + "' from "
382
+ newParent.getName(), superMethod.getSourceLocation()));
433
MessageUtil.error("Cannot reduce the visibility of the inherited method '" + superMethod
434
+ "' from " + newParent.getName(), superMethod.getSourceLocation()));
385
437
} else if (superMethod.isDefault()) {
386
438
if (subMethod.isPrivate()) {
387
weaver.getWorld().getMessageHandler().handleMessage(
388
MessageUtil.error("Cannot reduce the visibility of the inherited method '" + superMethod + "' from "
389
+ newParent.getName(), superMethod.getSourceLocation()));
442
MessageUtil.error("Cannot reduce the visibility of the inherited method '" + superMethod
443
+ "' from " + newParent.getName(), superMethod.getSourceLocation()));
432
489
boolean superMethodStatic = Modifier.isStatic(superMethod.getModifiers());
433
490
if (superMethodStatic && !subMethod.isStatic()) {
434
491
error(weaver, "This instance method " + subMethod.getName() + subMethod.getParameterSignature()
435
+ " cannot override the static method from " + superMethod.getDeclaringType().getName(), subMethod
436
.getSourceLocation(), new ISourceLocation[] { mungerLoc });
492
+ " cannot override the static method from " + superMethod.getDeclaringType().getName(),
493
subMethod.getSourceLocation(), new ISourceLocation[] { mungerLoc });
438
495
} else if (!superMethodStatic && subMethod.isStatic()) {
439
496
error(weaver, "The static method " + subMethod.getName() + subMethod.getParameterSignature()
440
+ " cannot hide the instance method from " + superMethod.getDeclaringType().getName(), subMethod
441
.getSourceLocation(), new ISourceLocation[] { mungerLoc });
497
+ " cannot hide the instance method from " + superMethod.getDeclaringType().getName(),
498
subMethod.getSourceLocation(), new ISourceLocation[] { mungerLoc });
582
639
if (onType.equals(gen.getType())) {
583
640
if (member.getKind() == Member.FIELD) {
584
641
// System.out.println("matched: " + gen);
585
addFieldGetter(gen, member, AjcMemberMaker
586
.privilegedAccessMethodForFieldGet(aspectType, member, munger.shortSyntax));
587
addFieldSetter(gen, member, AjcMemberMaker
588
.privilegedAccessMethodForFieldSet(aspectType, member, munger.shortSyntax));
642
addFieldGetter(gen, member,
643
AjcMemberMaker.privilegedAccessMethodForFieldGet(aspectType, member, munger.shortSyntax));
644
addFieldSetter(gen, member,
645
AjcMemberMaker.privilegedAccessMethodForFieldSet(aspectType, member, munger.shortSyntax));
590
647
} else if (member.getKind() == Member.METHOD) {
591
648
addMethodDispatch(gen, member, AjcMemberMaker.privilegedAccessMethodForMethod(aspectType, member));
593
650
} else if (member.getKind() == Member.CONSTRUCTOR) {
594
for (Iterator i = gen.getMethodGens().iterator(); i.hasNext();) {
595
LazyMethodGen m = (LazyMethodGen) i.next();
651
for (Iterator<LazyMethodGen> i = gen.getMethodGens().iterator(); i.hasNext();) {
652
LazyMethodGen m = i.next();
596
653
if (m.getMemberView() != null && m.getMemberView().getKind() == Member.CONSTRUCTOR) {
597
654
// m.getMemberView().equals(member)) {
938
995
ResolvedType rt = classGen.getType();
939
996
if (rt.isInterface()) {
940
997
ISourceLocation sloc = munger.getSourceLocation();
941
classWeaver.getWorld().getMessageHandler().handleMessage(
942
MessageUtil.error("ITD target " + rt.getName()
943
+ " is an interface but has been incorrectly determined to be the topmost implementor of "
944
+ onType.getName() + ". ITD is " + this.getSignature(), sloc));
1000
.getMessageHandler()
1005
+ " is an interface but has been incorrectly determined to be the topmost implementor of "
1006
+ onType.getName() + ". ITD is " + this.getSignature(), sloc));
946
1008
if (!onType.isAssignableFrom(rt)) {
947
1009
ISourceLocation sloc = munger.getSourceLocation();
948
classWeaver.getWorld().getMessageHandler().handleMessage(
949
MessageUtil.error("ITD target " + rt.getName() + " doesn't appear to implement " + onType.getName()
950
+ " why did we consider it the top most implementor? ITD is " + this.getSignature(), sloc));
1012
.getMessageHandler()
1015
"ITD target " + rt.getName() + " doesn't appear to implement " + onType.getName()
1016
+ " why did we consider it the top most implementor? ITD is "
1017
+ this.getSignature(), sloc));
952
1019
} else if (!rtx.isExposedToWeaver()) {
953
1020
ISourceLocation sLoc = munger.getSourceLocation();
954
classWeaver.getWorld().getMessageHandler().handleMessage(
955
MessageUtil.error(WeaverMessages.format(WeaverMessages.ITD_NON_EXPOSED_IMPLEMENTOR, rtx,
956
getAspectType().getName()), (sLoc == null ? getAspectType().getSourceLocation() : sLoc)));
1023
.getMessageHandler()
1025
MessageUtil.error(WeaverMessages.format(WeaverMessages.ITD_NON_EXPOSED_IMPLEMENTOR, rtx,
1026
getAspectType().getName()), (sLoc == null ? getAspectType().getSourceLocation() : sLoc)));
958
1028
// XXX what does this state mean?
959
1029
// We have incorrectly identified what is the top most