@Override public String toString() { StringBuilder stringBuilder = new StringBuilder(SYMBOL); TypeList.Generic bounds = getLowerBounds(); if (!bounds.isEmpty()) { stringBuilder.append(" super "); } else { bounds = getUpperBounds(); if (bounds.getOnly().equals(TypeDescription.Generic.OBJECT)) { return SYMBOL; } stringBuilder.append(" extends "); } return stringBuilder.append(bounds.getOnly().getTypeName()).toString(); }
@Override public String toString() { StringBuilder stringBuilder = new StringBuilder(); RenderingDelegate.CURRENT.apply(stringBuilder, asErasure(), getOwnerType()); TypeList.Generic typeArguments = getTypeArguments(); if (!typeArguments.isEmpty()) { stringBuilder.append('<'); boolean multiple = false; for (Generic typeArgument : typeArguments) { if (multiple) { stringBuilder.append(", "); } stringBuilder.append(typeArgument.getTypeName()); multiple = true; } stringBuilder.append('>'); } return stringBuilder.toString(); }
/** * Extracts the only method from a given type description which is validated for the required properties for * using the type as a proxy base type. * * @param typeDescription The type description to evaluate. * @return The only method which was found to be compatible to the proxy requirements. */ private static MethodDescription.InDefinedShape onlyMethod(TypeDescription typeDescription) { if (!typeDescription.isInterface()) { throw new IllegalArgumentException(typeDescription + " is not an interface"); } else if (!typeDescription.getInterfaces().isEmpty()) { throw new IllegalArgumentException(typeDescription + " must not extend other interfaces"); } else if (!typeDescription.isPublic()) { throw new IllegalArgumentException(typeDescription + " is not public"); } MethodList<MethodDescription.InDefinedShape> methodCandidates = typeDescription.getDeclaredMethods().filter(isAbstract()); if (methodCandidates.size() != 1) { throw new IllegalArgumentException(typeDescription + " must declare exactly one abstract method"); } return methodCandidates.getOnly(); }
generic = generic || !returnType.getSort().isNonGeneric(); TypeList.Generic exceptionTypes = getExceptionTypes(); if (!exceptionTypes.filter(not(ofSort(TypeDefinition.Sort.NON_GENERIC))).isEmpty()) { for (TypeDescription.Generic exceptionType : exceptionTypes) { exceptionType.accept(new TypeDescription.Generic.Visitor.ForSignatureVisitor(signatureWriter.visitExceptionType()));
/** * Creates a binder by installing a single proxy type where annotating a parameter with {@link FieldProxy} allows * getting and setting values for a given field. * * @param typeDescription A type which declares exactly one abstract getter and an abstract setter for the {@link Object} * type. The type is allowed to be generic. * @return A binder for the {@link FieldProxy} annotation. */ public static TargetMethodAnnotationDrivenBinder.ParameterBinder<FieldProxy> install(TypeDescription typeDescription) { if (!typeDescription.isInterface()) { throw new IllegalArgumentException(typeDescription + " is not an interface"); } else if (!typeDescription.getInterfaces().isEmpty()) { throw new IllegalArgumentException(typeDescription + " must not extend other interfaces"); } else if (!typeDescription.isPublic()) { throw new IllegalArgumentException(typeDescription + " is not public"); } MethodList<MethodDescription.InDefinedShape> methodCandidates = typeDescription.getDeclaredMethods().filter(isAbstract()); if (methodCandidates.size() != 2) { throw new IllegalArgumentException(typeDescription + " does not declare exactly two non-abstract methods"); } MethodList<MethodDescription.InDefinedShape> getterCandidates = methodCandidates.filter(isGetter(Object.class)); if (getterCandidates.size() != 1) { throw new IllegalArgumentException(typeDescription + " does not declare a getter with an Object type"); } MethodList<MethodDescription.InDefinedShape> setterCandidates = methodCandidates.filter(isSetter(Object.class)); if (setterCandidates.size() != 1) { throw new IllegalArgumentException(typeDescription + " does not declare a setter with an Object type"); } return new Binder(typeDescription, getterCandidates.getOnly(), setterCandidates.getOnly()); }
/** * Extracts the only method of a given type and validates to fit the constraints of the morph annotation. * * @param typeDescription The type to extract the method from. * @return The only method after validation. */ private static MethodDescription onlyMethod(TypeDescription typeDescription) { if (!typeDescription.isInterface()) { throw new IllegalArgumentException(typeDescription + " is not an interface"); } else if (!typeDescription.getInterfaces().isEmpty()) { throw new IllegalArgumentException(typeDescription + " must not extend other interfaces"); } else if (!typeDescription.isPublic()) { throw new IllegalArgumentException(typeDescription + " is mot public"); } MethodList<?> methodCandidates = typeDescription.getDeclaredMethods().filter(isAbstract()); if (methodCandidates.size() != 1) { throw new IllegalArgumentException(typeDescription + " must declare exactly one abstract method"); } MethodDescription methodDescription = methodCandidates.getOnly(); if (!methodDescription.getReturnType().asErasure().represents(Object.class)) { throw new IllegalArgumentException(methodDescription + " does not return an Object-type"); } else if (methodDescription.getParameters().size() != 1 || !methodDescription.getParameters().get(0).getType().asErasure().represents(Object[].class)) { throw new IllegalArgumentException(methodDescription + " does not take a single argument of type Object[]"); } return methodDescription; }
/** * Locates the only method of a type that is compatible to being overridden for invoking the proxy. * * @param typeDescription The type that is being installed. * @return Its only method after validation. */ private static MethodDescription onlyMethod(TypeDescription typeDescription) { if (!typeDescription.isInterface()) { throw new IllegalArgumentException(typeDescription + " is not an interface"); } else if (!typeDescription.getInterfaces().isEmpty()) { throw new IllegalArgumentException(typeDescription + " must not extend other interfaces"); } else if (!typeDescription.isPublic()) { throw new IllegalArgumentException(typeDescription + " is mot public"); } MethodList<?> methodCandidates = typeDescription.getDeclaredMethods().filter(isAbstract()); if (methodCandidates.size() != 1) { throw new IllegalArgumentException(typeDescription + " must declare exactly one abstract method"); } MethodDescription methodDescription = methodCandidates.getOnly(); if (!methodDescription.getReturnType().asErasure().represents(Object.class)) { throw new IllegalArgumentException(methodDescription + " does not return an Object-type"); } else if (methodDescription.getParameters().size() != 1 || !methodDescription.getParameters().getOnly().getType().asErasure().represents(Object.class)) { throw new IllegalArgumentException(methodDescription + " does not take a single Object-typed argument"); } return methodDescription; }
/** * {@inheritDoc} */ public FieldDescription resolve(TypeDescription targetType, ByteCodeElement target, TypeList.Generic parameters, TypeDescription.Generic result) { if (parameters.isEmpty()) { throw new IllegalStateException("Cannot substitute parameterless instruction with " + target); } else if (parameters.get(0).isPrimitive() || parameters.get(0).isArray()) { throw new IllegalStateException("Cannot access field on primitive or array type for " + target); } TypeDefinition current = parameters.get(0); do { FieldList<?> fields = current.getDeclaredFields().filter(not(isStatic()).<FieldDescription>and(isVisibleTo(instrumentedType)).and(matcher)); if (fields.size() == 1) { return fields.getOnly(); } else if (fields.size() > 1) { throw new IllegalStateException("Ambiguous field location of " + fields); } current = current.getSuperClass(); } while (current != null); throw new IllegalStateException("Cannot locate field matching " + matcher + " on " + targetType); } }
/** * {@inheritDoc} */ public MethodDescription resolve(TypeDescription targetType, ByteCodeElement target, TypeList.Generic parameters, TypeDescription.Generic result) { if (parameters.isEmpty()) { throw new IllegalStateException("Cannot substitute parameterless instruction with " + target); } else if (parameters.get(0).isPrimitive() || parameters.get(0).isArray()) { throw new IllegalStateException("Cannot invoke method on primitive or array type for " + target); } TypeDefinition typeDefinition = parameters.get(0); List<MethodDescription> candidates = CompoundList.<MethodDescription>of(methodGraphCompiler.compile(typeDefinition, instrumentedType) .listNodes() .asMethodList() .filter(matcher), typeDefinition.getDeclaredMethods().filter(isPrivate().<MethodDescription>and(isVisibleTo(instrumentedType)).and(matcher))); if (candidates.size() == 1) { return candidates.get(0); } else { throw new IllegalStateException("Not exactly one method that matches " + matcher + ": " + candidates); } } }
/** * {@inheritDoc} */ public TypeDescription.Generic onTypeVariable(TypeDescription.Generic typeVariable) { TypeList.Generic candidates = getTypeVariables().filter(named(typeVariable.getSymbol())); TypeDescription.Generic attached = candidates.isEmpty() ? instrumentedType.findVariable(typeVariable.getSymbol()) : candidates.getOnly(); if (attached == null) { throw new IllegalArgumentException("Cannot attach undefined variable: " + typeVariable); } else { return new TypeDescription.Generic.OfTypeVariable.WithAnnotationOverlay(attached, typeVariable); } } }
/** * {@inheritDoc} */ public SignatureVisitor onWildcard(Generic wildcard) { TypeList.Generic upperBounds = wildcard.getUpperBounds(), lowerBounds = wildcard.getLowerBounds(); if (lowerBounds.isEmpty() && upperBounds.getOnly().represents(Object.class)) { signatureVisitor.visitTypeArgument(); } else if (!lowerBounds.isEmpty() /* && upperBounds.isEmpty() */) { lowerBounds.getOnly().accept(new ForSignatureVisitor(signatureVisitor.visitTypeArgument(SignatureVisitor.SUPER))); } else /* if (!upperBounds.isEmpty() && lowerBounds.isEmpty()) */ { upperBounds.getOnly().accept(new ForSignatureVisitor(signatureVisitor.visitTypeArgument(SignatureVisitor.EXTENDS))); } return signatureVisitor; }
/** * {@inheritDoc} */ public TypeDescription.Generic findVariable(String symbol) { TypeList.Generic typeVariables = getTypeVariables().filter(named(symbol)); if (typeVariables.isEmpty()) { TypeVariableSource enclosingSource = getEnclosingSource(); return enclosingSource == null ? TypeDescription.Generic.UNDEFINED : enclosingSource.findVariable(symbol); } else { return typeVariables.getOnly(); } } }
/** * {@inheritDoc} */ public boolean isGenerified() { return !getTypeVariables().isEmpty(); }
/** * {@inheritDoc} */ public Boolean onWildcard(Generic wildcard) { if (!isValid(wildcard)) { return false; } TypeList.Generic lowerBounds = wildcard.getLowerBounds(); return (lowerBounds.isEmpty() ? wildcard.getUpperBounds() : lowerBounds).getOnly().accept(this); }
/** * {@inheritDoc} */ public Dispatcher onWildcard(Generic wildcard) { TypeList.Generic lowerBounds = wildcard.getLowerBounds(); return lowerBounds.isEmpty() ? new CovariantBinding(wildcard.getUpperBounds().getOnly()) : new ContravariantBinding(lowerBounds.getOnly()); }
/** * {@inheritDoc} */ public TypeDescription asErasure() { TypeList.Generic upperBounds = getUpperBounds(); return upperBounds.isEmpty() ? TypeDescription.OBJECT : upperBounds.get(0).asErasure(); }
/** * {@inheritDoc} */ public boolean isAssignableFrom(Generic typeDescription) { if (typeDescription.getSort().isWildcard()) { TypeList.Generic lowerBounds = typeDescription.getLowerBounds(); return !lowerBounds.isEmpty() && lowerBounds.getOnly().accept(Assigner.INSTANCE).isAssignableFrom(lowerBound); } else { return typeDescription.getSort().isWildcard() || typeDescription.accept(Assigner.INSTANCE).isAssignableFrom(lowerBound); } } }
/** * {@inheritDoc} */ public AnnotationAppender onWildcard(TypeDescription.Generic wildcard) { TypeList.Generic lowerBounds = wildcard.getLowerBounds(); return (lowerBounds.isEmpty() ? wildcard.getUpperBounds().getOnly() : lowerBounds.getOnly()).accept(new ForTypeAnnotations(apply(wildcard, typePath), annotationValueFilter, typeReference, typePath + WILDCARD_TYPE_PATH)); }
/** * {@inheritDoc} */ public boolean isGenerified() { if (!getTypeVariables().isEmpty()) { return true; } else if (isStatic()) { return false; } TypeDescription declaringType = getDeclaringType(); return declaringType != null && declaringType.isGenerified(); }
/** * {@inheritDoc} */ public boolean isAssignableFrom(Generic typeDescription) { if (typeDescription.getSort().isWildcard()) { return typeDescription.getLowerBounds().isEmpty() && upperBound.accept(Assigner.INSTANCE) .isAssignableFrom(typeDescription.getUpperBounds().getOnly()); } else { return upperBound.accept(Assigner.INSTANCE).isAssignableFrom(typeDescription); } } }