|
|
|
|
|
|
|
|
TypePattern typePattern = parseTypePattern(decpPattern, struct); |
|
|
TypePattern typePattern = parseTypePattern(decpPattern, struct); |
|
|
ResolvedType fieldType = UnresolvedType.forSignature(struct.field.getSignature()).resolve( |
|
|
ResolvedType fieldType = UnresolvedType.forSignature(struct.field.getSignature()).resolve( |
|
|
struct.enclosingType.getWorld()); |
|
|
struct.enclosingType.getWorld()); |
|
|
|
|
|
if (fieldType.isParameterizedOrRawType()) { |
|
|
|
|
|
fieldType = fieldType.getGenericType(); |
|
|
|
|
|
} |
|
|
if (fieldType.isInterface()) { |
|
|
if (fieldType.isInterface()) { |
|
|
TypePattern parent = parseTypePattern(fieldType.getName(), struct); |
|
|
TypePattern parent = parseTypePattern(fieldType.getName(), struct); |
|
|
FormalBinding[] bindings = new org.aspectj.weaver.patterns.FormalBinding[0]; |
|
|
FormalBinding[] bindings = new org.aspectj.weaver.patterns.FormalBinding[0]; |
|
|
|
|
|
|
|
|
hasNoCtorOrANoArgOne = false; |
|
|
hasNoCtorOrANoArgOne = false; |
|
|
|
|
|
|
|
|
if (resolvedMember.getParameterTypes().length == 0) { |
|
|
if (resolvedMember.getParameterTypes().length == 0) { |
|
|
if (defaultVisibilityImpl) { // default |
|
|
|
|
|
// visibility |
|
|
|
|
|
// implementation |
|
|
|
|
|
|
|
|
if (defaultVisibilityImpl) { // default visibility implementation |
|
|
if (resolvedMember.isPublic() || resolvedMember.isDefault()) { |
|
|
if (resolvedMember.isPublic() || resolvedMember.isDefault()) { |
|
|
hasNoCtorOrANoArgOne = true; |
|
|
hasNoCtorOrANoArgOne = true; |
|
|
} else { |
|
|
} else { |
|
|
|
|
|
|
|
|
Iterator<ResolvedMember> methodIterator = fieldType.getMethodsIncludingIntertypeDeclarations(false, true); |
|
|
Iterator<ResolvedMember> methodIterator = fieldType.getMethodsIncludingIntertypeDeclarations(false, true); |
|
|
while (methodIterator.hasNext()) { |
|
|
while (methodIterator.hasNext()) { |
|
|
ResolvedMember method = methodIterator.next(); |
|
|
ResolvedMember method = methodIterator.next(); |
|
|
|
|
|
|
|
|
// ResolvedMember[] methods = fieldType.getMethodsWithoutIterator(true, false, false).toArray( |
|
|
|
|
|
// new ResolvedMember[0]); |
|
|
|
|
|
// for (int i = 0; i < methods.length; i++) { |
|
|
|
|
|
// ResolvedMember method = methods[i]; |
|
|
|
|
|
if (method.isAbstract()) { |
|
|
if (method.isAbstract()) { |
|
|
// moved to be detected at weave time if the target |
|
|
// moved to be detected at weave time if the target |
|
|
// doesnt implement the methods |
|
|
// doesnt implement the methods |
|
|
|
|
|
|
|
|
// So here we create a modified method with an |
|
|
// So here we create a modified method with an |
|
|
// alternative declaring type so that we lookup |
|
|
// alternative declaring type so that we lookup |
|
|
// the right field. See pr164016. |
|
|
// the right field. See pr164016. |
|
|
MethodDelegateTypeMunger mdtm = new MethodDelegateTypeMunger(method, struct.enclosingType, |
|
|
|
|
|
defaultImplClassName, typePattern); |
|
|
|
|
|
|
|
|
MethodDelegateTypeMunger mdtm = new MethodDelegateTypeMunger(method, struct.enclosingType, defaultImplClassName, typePattern); |
|
|
mdtm.setFieldType(fieldType); |
|
|
mdtm.setFieldType(fieldType); |
|
|
mdtm.setSourceLocation(struct.enclosingType.getSourceLocation()); |
|
|
mdtm.setSourceLocation(struct.enclosingType.getSourceLocation()); |
|
|
struct.ajAttributes.add(new AjAttribute.TypeMunger(mdtm)); |
|
|
struct.ajAttributes.add(new AjAttribute.TypeMunger(mdtm)); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
// successfull so far, we thus need a bcel type munger to |
|
|
|
|
|
// have |
|
|
|
|
|
|
|
|
// successful so far, we thus need a bcel type munger to have |
|
|
// a field hosting the mixin in the target type |
|
|
// a field hosting the mixin in the target type |
|
|
if (hasAtLeastOneMethod && defaultImplClassName != null) { |
|
|
if (hasAtLeastOneMethod && defaultImplClassName != null) { |
|
|
ResolvedMember fieldHost = AjcMemberMaker.itdAtDeclareParentsField(null, fieldType, struct.enclosingType); |
|
|
ResolvedMember fieldHost = AjcMemberMaker.itdAtDeclareParentsField(null, fieldType, struct.enclosingType); |
|
|
struct.ajAttributes.add(new AjAttribute.TypeMunger(new MethodDelegateTypeMunger.FieldHostTypeMunger( |
|
|
struct.ajAttributes.add(new AjAttribute.TypeMunger(new MethodDelegateTypeMunger.FieldHostTypeMunger( |
|
|
fieldHost, struct.enclosingType, typePattern))); |
|
|
fieldHost, struct.enclosingType, typePattern))); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
return true; |
|
|
return true; |
|
|
} else { |
|
|
} else { |
|
|
reportError("@DeclareParents: can only be used on a field whose type is an interface", struct); |
|
|
reportError("@DeclareParents: can only be used on a field whose type is an interface", struct); |
|
|
|
|
|
|
|
|
// No annotation found |
|
|
// No annotation found |
|
|
return false; |
|
|
return false; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
Method annotatedMethod = struct.method; |
|
|
Method annotatedMethod = struct.method; |
|
|
World world = struct.enclosingType.getWorld(); |
|
|
World world = struct.enclosingType.getWorld(); |
|
|
NameValuePair declareMixinPatternNameValuePair = getAnnotationElement(declareMixinAnnotation, VALUE); |
|
|
NameValuePair declareMixinPatternNameValuePair = getAnnotationElement(declareMixinAnnotation, VALUE); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Return value of the annotated method is the interface or class that the mixin delegate should have |
|
|
// Return value of the annotated method is the interface or class that the mixin delegate should have |
|
|
ResolvedType methodReturnType = UnresolvedType.forSignature(annotatedMethod.getReturnType().getSignature()).resolve(world); |
|
|
ResolvedType methodReturnType = UnresolvedType.forSignature(annotatedMethod.getReturnType().getSignature()).resolve(world); |
|
|
|
|
|
|
|
|
|
|
|
if (methodReturnType.isParameterizedOrRawType()) { |
|
|
|
|
|
methodReturnType = methodReturnType.getGenericType(); |
|
|
|
|
|
} |
|
|
if (methodReturnType.isPrimitiveType()) { |
|
|
if (methodReturnType.isPrimitiveType()) { |
|
|
reportError(getMethodForMessage(struct) + ": factory methods for a mixin cannot return void or a primitive type", |
|
|
reportError(getMethodForMessage(struct) + ": factory methods for a mixin cannot return void or a primitive type", |
|
|
struct); |
|
|
struct); |
|
|
|
|
|
|
|
|
// supplied as a list in the 'Class[] interfaces' value in the annotation value |
|
|
// supplied as a list in the 'Class[] interfaces' value in the annotation value |
|
|
// supplied as just the interface return value of the annotated method |
|
|
// supplied as just the interface return value of the annotated method |
|
|
// supplied as just the class return value of the annotated method |
|
|
// supplied as just the class return value of the annotated method |
|
|
NameValuePair interfaceListSpecified = getAnnotationElement(declareMixinAnnotation, "interfaces"); |
|
|
|
|
|
|
|
|
NameValuePair interfaceListSpecified = getAnnotationElement(declareMixinAnnotation, "interfaces"); |
|
|
|
|
|
|
|
|
List<TypePattern> newParents = new ArrayList<TypePattern>(1); |
|
|
List<TypePattern> newParents = new ArrayList<TypePattern>(1); |
|
|
List<ResolvedType> newInterfaceTypes = new ArrayList<ResolvedType>(1); |
|
|
List<ResolvedType> newInterfaceTypes = new ArrayList<ResolvedType>(1); |