package net.bytebuddy.build;

import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.dynamic.ClassFileLocator;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.matcher.ElementMatcher;

/**
 * A plugin that allows for the application of Byte Buddy transformations during a build process. This plugin's
 * transformation is applied to any type matching this plugin's type matcher. Plugin types must be public,
 * non-abstract and must declare a public default constructor to work.
 */
@HashCodeAndEqualsPlugin.Enhance
public interface Plugin extends ElementMatcher<TypeDescription> {

    /**
     * Applies this plugin.
     *
     * @param builder          The builder to use as a basis for the applied transformation.
     * @param typeDescription  The type being transformed.
     * @param classFileLocator A class file locator that can locate other types in the scope of the project.
     * @return The supplied builder with additional transformations registered.
     */
    DynamicType.Builder<?> apply(DynamicType.Builder<?> builder, TypeDescription typeDescription, ClassFileLocator classFileLocator);

    /**
     * An abstract base for a {@link Plugin} that matches types by a given {@link ElementMatcher}.
     */
    abstract class ForElementMatcher implements Plugin {

        /**
         * The element matcher to apply.
         */
        private final ElementMatcher<? super TypeDescription> matcher;

        /**
         * Creates a new plugin that matches types using an element matcher.
         *
         * @param matcher The element matcher to apply.
         */
        protected ForElementMatcher(ElementMatcher<? super TypeDescription> matcher) {
            this.matcher = matcher;
        }

        @Override
        public boolean matches(TypeDescription target) {
            return matcher.matches(target);
        }
    }
}

@@ -213,16 +213,93 @@
 tcher;%0A%0A
+import java.util.ArrayList;%0Aimport java.util.Arrays;%0Aimport java.util.List;%0A%0A
 /**%0A * A
@@ -592,41 +592,8 @@
  */%0A
-@HashCodeAndEqualsPlugin.Enhance%0A
 publ
@@ -1182,16 +1182,549 @@
 ator);%0A%0A
+    /**%0A     * A non-operational plugin that does not instrument any type.%0A     */%0A    @HashCodeAndEqualsPlugin.Enhance%0A    class NoOp implements Plugin %7B%0A%0A        @Override%0A        public DynamicType.Builder%3C?%3E apply(DynamicType.Builder%3C?%3E builder, TypeDescription typeDescription, ClassFileLocator classFileLocator) %7B%0A            throw new IllegalStateException(%22Cannot apply non-operational plugin%22);%0A        %7D%0A%0A        @Override%0A        public boolean matches(TypeDescription target) %7B%0A            return false;%0A        %7D%0A    %7D%0A%0A
     /**%0A
@@ -1826,24 +1826,61 @@
 r%7D.%0A     */%0A
+    @HashCodeAndEqualsPlugin.Enhance%0A
     abstract
@@ -2431,32 +2431,32 @@
 ption target) %7B%0A
-
             retu
@@ -2498,11 +2498,1720 @@
  %7D%0A    %7D
+%0A%0A    /**%0A     * A compound plugin that applies several plugins in a row.%0A     */%0A    @HashCodeAndEqualsPlugin.Enhance%0A    class Compound implements Plugin %7B%0A%0A        /**%0A         * The plugins to apply.%0A         */%0A        private final List%3CPlugin%3E plugins;%0A%0A        /**%0A         * Creates a compound plugin.%0A         *%0A         * @param plugin The plugins to apply.%0A         */%0A        public Compound(Plugin... plugin) %7B%0A            this(Arrays.asList(plugin))%0A        %7D%0A%0A        /**%0A         * Creates a compound plugin.%0A         *%0A         * @param plugins The plugins to apply.%0A         */%0A        public Compound(List%3C? extends Plugin%3E plugins) %7B%0A            this.plugins = new ArrayList%3CPlugin%3E();%0A            for (Plugin plugin : plugins) %7B%0A                if (plugin instanceof Compound) %7B%0A                    this.plugins.addAll(((Compound) plugin).plugins);%0A                %7D else if (!(plugin instanceof NoOp)) %7B%0A                    this.plugins.add(plugin);%0A                %7D%0A            %7D%0A        %7D%0A%0A        @Override%0A        public DynamicType.Builder%3C?%3E apply(DynamicType.Builder%3C?%3E builder, TypeDescription typeDescription, ClassFileLocator classFileLocator) %7B%0A            for (Plugin plugin : plugins) %7B%0A                if (plugin.matches(typeDescription)) %7B%0A                    builder = plugin.apply(builder, typeDescription, classFileLocator);%0A                %7D%0A            %7D%0A            return builder;%0A        %7D%0A%0A        @Override%0A        public boolean matches(TypeDescription target) %7B%0A            for (Plugin plugin : plugins) %7B%0A                if (plugin.matches(target)) %7B%0A                    return true;%0A                %7D%0A            %7D%0A            return false;%0A        %7D%0A    %7D
 %0A%7D%0A

Add additional plugin abstractions.