package com.github.tmurakami.dexopener;

import android.app.Instrumentation;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.support.annotation.NonNull;

/**
 * This is an object that provides the ability to mock final classes and methods.
 */
@SuppressWarnings("WeakerAccess")
public abstract class DexOpener {

    DexOpener() {
    }

    /**
     * Provides the ability to mock final classes and methods.
     * <p>
     * This is equivalent to the following code:
     * <pre>{@code
     * Context context = instrumentation.getTargetContext();
     * builder(context).build().installTo(context.getClassLoader());
     * }</pre>
     *
     * @param instrumentation the instrumentation
     * @see #installTo(ClassLoader)
     */
    public static void install(@NonNull Instrumentation instrumentation) {
        Context context = instrumentation.getTargetContext();
        if (context == null) {
            throw new IllegalArgumentException("'instrumentation' has not been initialized yet");
        }
        builder(context).build().installTo(context.getClassLoader());
    }

    /**
     * Provides the ability to mock final classes and methods.
     * After calling this method, you can mock classes loaded by the given class loader.
     * <p>
     * Note that final classes loaded before calling this cannot be mocked.
     *
     * @param classLoader the class loader
     * @deprecated use {@link #installTo(ClassLoader)} instead
     */
    @Deprecated
    public final void install(@NonNull ClassLoader classLoader) {
        installTo(classLoader);
    }

    /**
     * Provides the ability to mock final classes and methods.
     * After calling this method, you can mock classes loaded by the given class loader.
     * <p>
     * Note that final classes loaded before calling this cannot be mocked.
     *
     * @param classLoader the class loader
     */
    public abstract void installTo(@NonNull ClassLoader classLoader);

    /**
     * Instantiates a new {@link Builder} instance.
     *
     * @param context the context
     * @return the {@link Builder}
     */
    @NonNull
    public static Builder builder(@NonNull Context context) {
        return new Builder(context.getApplicationInfo());
    }

    /**
     * The builder for {@link DexOpener}.
     */
    public static final class Builder {

        private final ApplicationInfo applicationInfo;
        private ClassNameFilter classNameFilter = AcceptAll.INSTANCE;

        Builder(ApplicationInfo applicationInfo) {
            this.applicationInfo = applicationInfo;
        }

        /**
         * Throws an {@link UnsupportedOperationException}.
         *
         * @throws UnsupportedOperationException this method is deprecated
         * @deprecated use {@link #classNameFilter(ClassNameFilter)} instead.
         */
        @Deprecated
        @NonNull
        public Builder classNameFilters(@SuppressWarnings("unused") @NonNull ClassNameFilter... filters)
                throws UnsupportedOperationException {
            throw new UnsupportedOperationException("Use classNameFilter(ClassNameFilter) instead");
        }

        /**
         * Sets a {@link ClassNameFilter}.
         *
         * @param filter the {@link ClassNameFilter}
         * @return this builder
         */
        @NonNull
        public Builder classNameFilter(@NonNull ClassNameFilter filter) {
            classNameFilter = filter;
            return this;
        }

        /**
         * Instantiates a new {@link DexOpener} instance.
         *
         * @return the {@link DexOpener}
         */
        @NonNull
        public DexOpener build() {
            return new DexOpenerImpl(applicationInfo,
                                     new ClassNameFilterWrapper(classNameFilter),
                                     DexFileLoader.INSTANCE,
                                     DexClassFileFactory.INSTANCE);
        }

    }

}

@@ -2802,16 +2802,52 @@
  %7B@link 
+#openIf(ClassNameFilter)%7D or %7B@link 
 #classNa
@@ -2882,16 +2882,16 @@
 nstead.%0A
-
         
@@ -3147,54 +3147,688 @@
 ion(
-%22Use classNameFilter(ClassNameFilter) instead%22
+%0A                    %22Use openIf(ClassNameFilter) or classNameFilter(ClassNameFilter) instead%22);%0A        %7D%0A%0A        /**%0A         * Sets a %7B@link ClassNameFilter%7D.%0A         * This is an alias of %7B@link #classNameFilter(ClassNameFilter)%7D. Using this makes code more%0A         * readable with lambda expressions, as in the following code:%0A         * %3Cpre%3E%7B@code%0A         * openIf(name -%3E name.startsWith(%22package.you.want.to.mock.%22))%0A         * %7D%3C/pre%3E%0A         *%0A         * @param filter the %7B@link ClassNameFilter%7D%0A         * @return this builder%0A         */%0A        @NonNull%0A        public Builder openIf(@NonNull ClassNameFilter filter) %7B%0A            return classNameFilter(filter
 );%0A 

Add `DexOpener.Builder#openIf(ClassNameFilter)`