All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.fitbur.bytebuddy.dynamic.scaffold.inline.InliningImplementationMatcher Maven / Gradle / Ivy

There is a newer version: 1.0.0
Show newest version
package com.fitbur.bytebuddy.dynamic.scaffold.inline;

import com.fitbur.bytebuddy.description.method.MethodDescription;
import com.fitbur.bytebuddy.description.type.TypeDescription;
import com.fitbur.bytebuddy.matcher.ElementMatcher;
import com.fitbur.bytebuddy.matcher.ElementMatchers;
import com.fitbur.bytebuddy.matcher.LatentMatcher;

import static com.fitbur.bytebuddy.matcher.ElementMatchers.*;

/**
 * A latent method matcher that identifies methods to instrument when redefining or rebasing a type.
 */
public class InliningImplementationMatcher implements LatentMatcher {

    /**
     * A method matcher that matches any ignored method.
     */
    private final LatentMatcher ignoredMethods;

    /**
     * A method matcher that matches any predefined method.
     */
    private final ElementMatcher predefinedMethodSignatures;

    /**
     * Creates a new inline implementation matcher.
     *
     * @param ignoredMethods             A method matcher that matches any ignored method.
     * @param predefinedMethodSignatures A method matcher that matches any predefined method.
     */
    protected InliningImplementationMatcher(LatentMatcher ignoredMethods,
                                            ElementMatcher predefinedMethodSignatures) {
        this.ignoredMethods = ignoredMethods;
        this.predefinedMethodSignatures = predefinedMethodSignatures;
    }

    /**
     * Creates a matcher where only overridable or declared methods are matched unless those are ignored. Methods that
     * are declared by the target type are only matched if they are not ignored. Declared methods that are not found on the
     * target type are always matched.
     *
     * @param ignoredMethods A method matcher that matches any ignored method.
     * @param originalType   The original type of the instrumentation before adding any user methods.
     * @return A latent method matcher that identifies any method to instrument for a rebasement or redefinition.
     */
    protected static LatentMatcher of(LatentMatcher ignoredMethods, TypeDescription originalType) {
        ElementMatcher.Junction predefinedMethodSignatures = none();
        for (MethodDescription methodDescription : originalType.getDeclaredMethods()) {
            ElementMatcher.Junction signature = methodDescription.isConstructor()
                    ? isConstructor()
                    : ElementMatchers.named(methodDescription.getName());
            signature = signature.and(returns(methodDescription.getReturnType().asErasure()));
            signature = signature.and(takesArguments(methodDescription.getParameters().asTypeList().asErasures()));
            predefinedMethodSignatures = predefinedMethodSignatures.or(signature);
        }
        return new InliningImplementationMatcher(ignoredMethods, predefinedMethodSignatures);
    }

    @Override
    public ElementMatcher resolve(TypeDescription instrumentedType) {
        return (ElementMatcher) not(ignoredMethods.resolve(instrumentedType))
                .and(isVirtual().and(not(isFinal())).or(isDeclaredBy(instrumentedType)))
                .or(isDeclaredBy(instrumentedType).and(not(predefinedMethodSignatures)));
    }

    @Override
    public boolean equals(Object other) {
        return this == other || !(other == null || getClass() != other.getClass())
                && ignoredMethods.equals(((InliningImplementationMatcher) other).ignoredMethods)
                && predefinedMethodSignatures.equals(((InliningImplementationMatcher) other).predefinedMethodSignatures);
    }

    @Override
    public int hashCode() {
        return 31 * ignoredMethods.hashCode() + predefinedMethodSignatures.hashCode();
    }

    @Override
    public String toString() {
        return "InliningImplementationMatcher{" +
                "ignoredMethods=" + ignoredMethods +
                ", predefinedMethodSignatures=" + predefinedMethodSignatures +
                '}';
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy