/** * Delegates any intercepted method to invoke a {@code static} method that is declared by the supplied type. To be considered * a valid delegation target, the target method must be visible and accessible to the instrumented type. This is the case if * the target type is either public or in the same package as the instrumented type and if the target method is either public * or non-private and in the same package as the instrumented type. Private methods can only be used as a delegation target if * the delegation is targeting the instrumented type. * * @param typeDescription The target type for the delegation. * @return A method delegation that redirects method calls to a static method of the supplied type. */ public MethodDelegation to(TypeDescription typeDescription) { if (typeDescription.isArray()) { throw new IllegalArgumentException("Cannot delegate to array " + typeDescription); } else if (typeDescription.isPrimitive()) { throw new IllegalArgumentException("Cannot delegate to primitive " + typeDescription); } return new MethodDelegation(ImplementationDelegate.ForStaticMethod.of(typeDescription.getDeclaredMethods().filter(isStatic().and(matcher)), TargetMethodAnnotationDrivenBinder.of(parameterBinders)), parameterBinders, ambiguityResolver, bindingResolver); }
/** * {@inheritDoc} */ public ByteCodeAppender appender(Target implementationTarget) { if (implementationTarget.getInstrumentedType().isInterface()) { throw new IllegalStateException("Cannot implement meaningful hash code method for " + implementationTarget.getInstrumentedType()); } return new Appender(offsetProvider.resolve(implementationTarget.getInstrumentedType()), multiplier, implementationTarget.getInstrumentedType().getDeclaredFields().filter(not(isStatic().or(ignored))), nonNullable); }
/** * {@inheritDoc} */ public Appender appender(Target implementationTarget) { if (implementationTarget.getInstrumentedType().isInterface()) { throw new IllegalStateException("Cannot implement meaningful toString method for " + implementationTarget.getInstrumentedType()); } String prefix = prefixResolver.resolve(implementationTarget.getInstrumentedType()); if (prefix == null) { throw new IllegalStateException("Prefix for toString method cannot be null"); } return new Appender(prefix, start, end, separator, definer, implementationTarget.getInstrumentedType().getDeclaredFields().filter(not(isStatic().or(ignored)))); }
/** * {@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 ByteCodeAppender appender(Target implementationTarget) { if (implementationTarget.getInstrumentedType().isInterface()) { throw new IllegalStateException("Cannot implement meaningful equals method for " + implementationTarget.getInstrumentedType()); } List<FieldDescription.InDefinedShape> fields = new ArrayList<FieldDescription.InDefinedShape>(implementationTarget.getInstrumentedType() .getDeclaredFields() .filter(not(isStatic().or(ignored)))); Collections.sort(fields, comparator); return new Appender(implementationTarget.getInstrumentedType(), new StackManipulation.Compound( superClassCheck.resolve(implementationTarget.getInstrumentedType()), MethodVariableAccess.loadThis(), MethodVariableAccess.REFERENCE.loadFrom(1), ConditionalReturn.onIdentity().returningTrue(), typeCompatibilityCheck.resolve(implementationTarget.getInstrumentedType()) ), fields, nonNullable); }
/** * {@inheritDoc} */ public Compiled compile(TypeDescription instrumentedType) { MethodList<?> targets = new MethodList.Explicit<MethodDescription>(CompoundList.<MethodDescription>of( instrumentedType.getDeclaredMethods().filter(isStatic().or(isPrivate())), methodGraphCompiler.compile(instrumentedType).listNodes().asMethodList()) ).filter(named(name).and(takesArguments(0)).and(not(returns(isPrimitive().or(isArray()))))); if (targets.size() != 1) { throw new IllegalStateException(instrumentedType + " does not define method without arguments with name " + name + ": " + targets); } else if (!targets.getOnly().getReturnType().asErasure().isVisibleTo(instrumentedType)) { throw new IllegalStateException(targets.getOnly() + " is not visible to " + instrumentedType); } else { MethodList<?> candidates = methodGraphCompiler.compile(targets.getOnly().getReturnType(), instrumentedType) .listNodes() .asMethodList() .filter(matcher); List<MethodDelegationBinder.Record> records = new ArrayList<MethodDelegationBinder.Record>(candidates.size()); MethodDelegationBinder methodDelegationBinder = TargetMethodAnnotationDrivenBinder.of(parameterBinders); for (MethodDescription candidate : candidates) { records.add(methodDelegationBinder.compile(candidate)); } return new Compiled.ForMethodReturn(targets.get(0), records); } }
} else { // Invokevirtual and invokeinterface can represent a private, non-static method from Java 11. candidates = resolution.resolve().getDeclaredMethods().filter(strict ? ElementMatchers.<MethodDescription>isPrivate().and(not(isStatic())).and(named(internalName).and(hasDescriptor(descriptor))) : ElementMatchers.<MethodDescription>failSafe(isPrivate().<MethodDescription>and(not(isStatic())).and(named(internalName).and(hasDescriptor(descriptor))))); if (candidates.isEmpty()) { candidates = methodGraphCompiler.compile(resolution.resolve(), instrumentedType).listNodes().asMethodList().filter(strict
@Override public final boolean matches(TypeDescription target) { return target.getDeclaredFields() .filter(not(isStatic())) .isEmpty(); } }
@Override public final boolean matches(TypeDescription target) { MethodList<MethodDescription.InDefinedShape> declaredMethods = target.getDeclaredMethods() .filter(isStatic()) .filter(not(isSynthetic())); if(target.isEnum()) { declaredMethods = declaredMethods .filter(not(ENUM_METHODS_MATCHER)); } return declaredMethods.isEmpty(); } }
.to(MockKProxyAdvice.class).on( isMethod() .and(not(isStatic())) .and(not(isDefaultFinalizer())))) .visit(Advice.withCustomMapping() .bind(MockKProxyAdviceId.class, staticProxyAdviceId(className)) .to(staticProxyAdvice(className)).on( isStatic() .and(not(isTypeInitializer())) .and(not(isConstructor()))
@Override public final boolean matches(TypeDescription target) { MethodList<MethodDescription.InDefinedShape> methodsToCheck = target.getDeclaredMethods() .filter(not(isConstructor())) .filter(isPublic()) .filter(not(isStatic())) .filter(not(isBridge())) .filter(not(named("equals"))) .filter(not(named("hashCode"))) .filter(not(named("toString"))); for(MethodDescription md : methodsToCheck) { if(!md.isFinal()) { return false; } } return true; } }