<commit_before>/*
 * Copyright 2014 - Present <NAME>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package net.bytebuddy.asm;

import net.bytebuddy.ByteBuddy;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.modifier.FieldManifestation;
import net.bytebuddy.description.modifier.Ownership;
import net.bytebuddy.description.modifier.Visibility;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.dynamic.loading.MultipleParentClassLoader;
import net.bytebuddy.dynamic.scaffold.TypeValidation;
import net.bytebuddy.dynamic.scaffold.subclass.ConstructorStrategy;
import net.bytebuddy.implementation.ExceptionMethod;
import net.bytebuddy.implementation.FieldAccessor;
import net.bytebuddy.implementation.Implementation;
import net.bytebuddy.implementation.MethodCall;
import net.bytebuddy.implementation.bytecode.ByteCodeAppender;
import net.bytebuddy.implementation.bytecode.Duplication;
import net.bytebuddy.implementation.bytecode.StackManipulation;
import net.bytebuddy.implementation.bytecode.TypeCreation;
import net.bytebuddy.implementation.bytecode.assign.Assigner;
import net.bytebuddy.implementation.bytecode.member.MethodInvocation;
import net.bytebuddy.implementation.bytecode.member.MethodReturn;
import net.bytebuddy.implementation.bytecode.member.MethodVariableAccess;
import net.bytebuddy.matcher.ElementMatchers;
import net.bytebuddy.utility.OpenedClassReader;
import org.objectweb.asm.*;

import java.lang.reflect.Method;
import java.util.*;

import static net.bytebuddy.matcher.ElementMatchers.is;
import static net.bytebuddy.matcher.ElementMatchers.named;

public abstract class ClassVisitorFactory<T> {

    private static final Object[] EMPTY = new Object[0];

    private static final String DELEGATE = "delegate";

    private static final String LABELS = "labels";

    private static final String WRAP = "wrap";

    public static <S> ClassVisitorFactory<S> of(Class<S> classVisitor) {
        return of(classVisitor, new ByteBuddy().with(TypeValidation.DISABLED));
    }

    public static <S> ClassVisitorFactory<S> of(Class<S> classVisitor, ByteBuddy byteBuddy) {
        try {
            String prefix = classVisitor.getPackage().getName();
            Map<Class<?>, Class<?>> utilities = new HashMap<Class<?>, Class<?>>();
            for (Class<?> type : Arrays.asList(
                    Attribute.class,
                    Label.class,
                    Type.class,
                    TypePath.class,
                    Handle.class,
                    ConstantDynamic.class
            )) {
                utilities.put(type, Class.forName(prefix + "." + type.getSimpleName()));
            }
            Map<Class<?>, Class<?>> equivalents = new HashMap<Class<?>, Class<?>>();
            Map<Class<?>, DynamicType.Builder<?>> builders = new HashMap<Class<?>, DynamicType.Builder<?>>();
            for (Class<?> type : Arrays.asList(
                    ClassVisitor.class,
                    AnnotationVisitor.class,
                    FieldVisitor.class,
                    MethodVisitor.class,
                    RecordComponentVisitor.class,
                    ModuleVisitor.class
            )) {
                Class<?> equivalent = Class.forName(prefix + "." + type.getSimpleName());
                DynamicType.Builder<?> wrapper, unwrapper;
                if (type == MethodVisitor.class) {
                    wrapper = toMethodVisitorBuilder(byteBuddy,
                            type, equivalent,
                            TypePath.class, utilities.get(TypePath.class),
                            Label.class, utilities.get(Label.class),
                            Type.class, utilities.get(Type.class),
                            Handle.class, utilities.get(Handle.class),
                            ConstantDynamic.class, utilities.get(ConstantDynamic.class));
                    unwrapper = toMethodVisitorBuilder(byteBuddy,
                            equivalent, type,
                            utilities.get(TypePath.class), TypePath.class,
                            utilities.get(Label.class), Label.class,
                            utilities.get(Type.class), Type.class,
                            utilities.get(Handle.class), Handle.class,
                            utilities.get(ConstantDynamic.class), ConstantDynamic.class);
                } else {
                    wrapper = toBuilder(byteBuddy,
                            type, equivalent,
                            TypePath.class, utilities.get(TypePath.class),
                            new Implementation.Simple(MethodReturn.VOID));
                    unwrapper = toBuilder(byteBuddy,
                            equivalent, type,
                            utilities.get(TypePath.class), TypePath.class,
                            new Implementation.Simple(MethodReturn.VOID));
                }
                equivalents.put(type, equivalent);
                builders.put(type, wrapper);
                builders.put(equivalent, unwrapper);
            }
            List<DynamicType> dynamicTypes = new ArrayList<DynamicType>();
            Map<Class<?>, TypeDescription> generated = new HashMap<Class<?>, TypeDescription>();
            for (Map.Entry<Class<?>, Class<?>> entry : equivalents.entrySet()) {
                DynamicType.Builder<?> wrapper = builders.get(entry.getKey()), unwrapper = builders.get(entry.getValue());
                for (Method method : entry.getKey().getMethods()) {
                    if (method.getDeclaringClass() == Object.class) {
                        continue;
                    }
                    Class<?>[] parameter = method.getParameterTypes(), match = new Class<?>[parameter.length];
                    List<MethodCall.ArgumentLoader.Factory> left = new ArrayList<MethodCall.ArgumentLoader.Factory>(parameter.length);
                    List<MethodCall.ArgumentLoader.Factory> right = new ArrayList<MethodCall.ArgumentLoader.Factory>(match.length);
                    boolean unsupported = false;
                    for (int index = 0; index < parameter.length; index++) {
                        if (entry.getKey() == MethodVisitor.class && parameter[index] == Label.class) {
                            match[index] = utilities.get(Label.class);
                            left.add(toConvertedParameter(builders.get(entry.getKey()).toTypeDescription(), match[index], LabelTranslator.NAME, index, true));
                            right.add(toConvertedParameter(builders.get(entry.getValue()).toTypeDescription(), parameter[index], LabelTranslator.NAME, index, true));
                        } else if (entry.getKey() == MethodVisitor.class && parameter[index] == Label[].class) {
                            match[index] = Class.forName("[L" + utilities.get(Label.class).getName() + ";", false, classVisitor.getClassLoader());
                            left.add(toConvertedParameter(builders.get(entry.getKey()).toTypeDescription(), match[index], LabelArrayTranslator.NAME, index, true));
                            right.add(toConvertedParameter(builders.get(entry.getValue()).toTypeDescription(), parameter[index], LabelArrayTranslator.NAME, index, true));
                        } else if (parameter[index] == TypePath.class) {
                            match[index] = utilities.get(TypePath.class);
                            left.add(toConvertedParameter(builders.get(entry.getKey()).toTypeDescription(), match[index], TypePathTranslator.NAME, index, false));
                            right.add(toConvertedParameter(builders.get(entry.getValue()).toTypeDescription(), parameter[index], TypePathTranslator.NAME, index, false));
                        } else if (entry.getKey() == MethodVisitor.class && parameter[index] == Handle.class) {
                            match[index] = utilities.get(Handle.class);
                            left.add(toConvertedParameter(builders.get(entry.getKey()).toTypeDescription(), match[index], HandleTranslator.NAME, index, false));
                            right.add(toConvertedParameter(builders.get(entry.getValue()).toTypeDescription(), parameter[index], HandleTranslator.NAME, index, false));
                        } else if (entry.getKey() == MethodVisitor.class && parameter[index] == Object.class) {
                            match[index] = Object.class;
                            left.add(toConvertedParameter(builders.get(entry.getKey()).toTypeDescription(), Object.class, ConstantTranslator.NAME, index, false));
                            right.add(toConvertedParameter(builders.get(entry.getValue()).toTypeDescription(), Object.class, ConstantTranslator.NAME, index, false));
                        } else if (entry.getKey() == MethodVisitor.class && parameter[index] == Object[].class) {
                            match[index] = Object[].class;
                            if (method.getName().equals("visitFrame")) {
                                left.add(toConvertedParameter(builders.get(entry.getKey()).toTypeDescription(), Object[].class, FrameTranslator.NAME, index, true));
                                right.add(toConvertedParameter(builders.get(entry.getValue()).toTypeDescription(), Object[].class, FrameTranslator.NAME, index, true));
                            } else {
                                left.add(toConvertedParameter(builders.get(entry.getKey()).toTypeDescription(), Object[].class, ConstantArrayTranslator.NAME, index, false));
                                right.add(toConvertedParameter(builders.get(entry.getValue()).toTypeDescription(), Object[].class, ConstantArrayTranslator.NAME, index, false));
                            }
                        } else if (parameter[index] == Attribute.class) {
                            match[index] = utilities.get(Attribute.class);
                            unsupported = true;
                        } else {
                            match[index] = parameter[index];
                            left.add(new MethodCall.ArgumentLoader.ForMethodParameter.Factory(index));
                            right.add(new MethodCall.ArgumentLoader.ForMethodParameter.Factory(index));
                        }
                    }
                    Method target = entry.getValue().getMethod(method.getName(), match);
                    if (unsupported) {<commit_msg>Add resilience with older ASM versions.<commit_after>/*
 * Copyright 2014 - Present <NAME>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package net.bytebuddy.asm;

import net.bytebuddy.ByteBuddy;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.modifier.FieldManifestation;
import net.bytebuddy.description.modifier.Ownership;
import net.bytebuddy.description.modifier.Visibility;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.dynamic.loading.MultipleParentClassLoader;
import net.bytebuddy.dynamic.scaffold.TypeValidation;
import net.bytebuddy.dynamic.scaffold.subclass.ConstructorStrategy;
import net.bytebuddy.implementation.ExceptionMethod;
import net.bytebuddy.implementation.FieldAccessor;
import net.bytebuddy.implementation.Implementation;
import net.bytebuddy.implementation.MethodCall;
import net.bytebuddy.implementation.bytecode.ByteCodeAppender;
import net.bytebuddy.implementation.bytecode.Duplication;
import net.bytebuddy.implementation.bytecode.StackManipulation;
import net.bytebuddy.implementation.bytecode.TypeCreation;
import net.bytebuddy.implementation.bytecode.assign.Assigner;
import net.bytebuddy.implementation.bytecode.member.MethodInvocation;
import net.bytebuddy.implementation.bytecode.member.MethodReturn;
import net.bytebuddy.implementation.bytecode.member.MethodVariableAccess;
import net.bytebuddy.matcher.ElementMatchers;
import net.bytebuddy.utility.OpenedClassReader;
import org.objectweb.asm.*;

import java.lang.reflect.Method;
import java.util.*;

import static net.bytebuddy.matcher.ElementMatchers.is;
import static net.bytebuddy.matcher.ElementMatchers.named;

public abstract class ClassVisitorFactory<T> {

    private static final Object[] EMPTY = new Object[0];

    private static final String DELEGATE = "delegate";

    private static final String LABELS = "labels";

    private static final String WRAP = "wrap";

    public static <S> ClassVisitorFactory<S> of(Class<S> classVisitor) {
        return of(classVisitor, new ByteBuddy().with(TypeValidation.DISABLED));
    }

    public static <S> ClassVisitorFactory<S> of(Class<S> classVisitor, ByteBuddy byteBuddy) {
        try {
            String prefix = classVisitor.getPackage().getName();
            Map<Class<?>, Class<?>> utilities = new HashMap<Class<?>, Class<?>>();
            for (Class<?> type : Arrays.asList(
                    Attribute.class,
                    Label.class,
                    Type.class,
                    TypePath.class,
                    Handle.class,
                    ConstantDynamic.class
            )) {
                Class<?> utility;
                try {
                    utility = Class.forName(prefix + "." + type.getSimpleName());
                } catch (ClassNotFoundException ignored) {
                    continue;
                }
                utilities.put(type, utility);
            }
            Map<Class<?>, Class<?>> equivalents = new HashMap<Class<?>, Class<?>>();
            Map<Class<?>, DynamicType.Builder<?>> builders = new HashMap<Class<?>, DynamicType.Builder<?>>();
            for (Class<?> type : Arrays.asList(
                    ClassVisitor.class,
                    AnnotationVisitor.class,
                    FieldVisitor.class,
                    MethodVisitor.class,
                    RecordComponentVisitor.class,
                    ModuleVisitor.class
            )) {
                Class<?> equivalent;
                try {
                    equivalent = Class.forName(prefix + "." + type.getSimpleName());
                } catch (ClassNotFoundException ignored) {
                    continue;
                }
                DynamicType.Builder<?> wrapper, unwrapper;
                if (type == MethodVisitor.class) {
                    wrapper = toMethodVisitorBuilder(byteBuddy,
                            type, equivalent,
                            TypePath.class, utilities.get(TypePath.class),
                            Label.class, utilities.get(Label.class),
                            Type.class, utilities.get(Type.class),
                            Handle.class, utilities.get(Handle.class),
                            ConstantDynamic.class, utilities.get(ConstantDynamic.class));
                    unwrapper = toMethodVisitorBuilder(byteBuddy,
                            equivalent, type,
                            utilities.get(TypePath.class), TypePath.class,
                            utilities.get(Label.class), Label.class,
                            utilities.get(Type.class), Type.class,
                            utilities.get(Handle.class), Handle.class,
                            utilities.get(ConstantDynamic.class), ConstantDynamic.class);
                } else {
                    wrapper = toBuilder(byteBuddy,
                            type, equivalent,
                            TypePath.class, utilities.get(TypePath.class),
                            new Implementation.Simple(MethodReturn.VOID));
                    unwrapper = toBuilder(byteBuddy,
                            equivalent, type,
                            utilities.get(TypePath.class), TypePath.class,
                            new Implementation.Simple(MethodReturn.VOID));
                }
                equivalents.put(type, equivalent);
                builders.put(type, wrapper);
                builders.put(equivalent, unwrapper);
            }
            List<DynamicType> dynamicTypes = new ArrayList<DynamicType>();
            Map<Class<?>, TypeDescription> generated = new HashMap<Class<?>, TypeDescription>();
            for (Map.Entry<Class<?>, Class<?>> entry : equivalents.entrySet()) {
                DynamicType.Builder<?> wrapper = builders.get(entry.getKey()), unwrapper = builders.get(entry.getValue());
                for (Method method : entry.getKey().getMethods()) {
                    if (method.getDeclaringClass() == Object.class) {
                        continue;
                    }
                    Class<?>[] parameter = method.getParameterTypes(), match = new Class<?>[parameter.length];
                    List<MethodCall.ArgumentLoader.Factory> left = new ArrayList<MethodCall.ArgumentLoader.Factory>(parameter.length);
                    List<MethodCall.ArgumentLoader.Factory> right = new ArrayList<MethodCall.ArgumentLoader.Factory>(match.length);
                    boolean unsupported = false;
                    for (int index = 0; index < parameter.length; index++) {
                        if (entry.getKey() == MethodVisitor.class && parameter[index] == Label.class) {
                            match[index] = utilities.get(Label.class);
                            left.add(toConvertedParameter(builders.get(entry.getKey()).toTypeDescription(), match[index], LabelTranslator.NAME, index, true));
                            right.add(toConvertedParameter(builders.get(entry.getValue()).toTypeDescription(), parameter[index], LabelTranslator.NAME, index, true));
                        } else if (entry.getKey() == MethodVisitor.class && parameter[index] == Label[].class) {
                            match[index] = Class.forName("[L" + utilities.get(Label.class).getName() + ";", false, classVisitor.getClassLoader());
                            left.add(toConvertedParameter(builders.get(entry.getKey()).toTypeDescription(), match[index], LabelArrayTranslator.NAME, index, true));
                            right.add(toConvertedParameter(builders.get(entry.getValue()).toTypeDescription(), parameter[index], LabelArrayTranslator.NAME, index, true));
                        } else if (parameter[index] == TypePath.class) {
                            match[index] = utilities.get(TypePath.class);
                            left.add(toConvertedParameter(builders.get(entry.getKey()).toTypeDescription(), match[index], TypePathTranslator.NAME, index, false));
                            right.add(toConvertedParameter(builders.get(entry.getValue()).toTypeDescription(), parameter[index], TypePathTranslator.NAME, index, false));
                        } else if (entry.getKey() == MethodVisitor.class && parameter[index] == Handle.class) {
                            match[index] = utilities.get(Handle.class);
                            left.add(toConvertedParameter(builders.get(entry.getKey()).toTypeDescription(), match[index], HandleTranslator.NAME, index, false));
                            right.add(toConvertedParameter(builders.get(entry.getValue()).toTypeDescription(), parameter[index], HandleTranslator.NAME, index, false));
                        } else if (entry.getKey() == MethodVisitor.class && parameter[index] == Object.class) {
                            match[index] = Object.class;
                            left.add(toConvertedParameter(builders.get(entry.getKey()).toTypeDescription(), Object.class, ConstantTranslator.NAME, index, false));
                            right.add(toConvertedParameter(builders.get(entry.getValue()).toTypeDescription(), Object.class, ConstantTranslator.NAME, index, false));
                        } else if (entry.getKey() == MethodVisitor.class && parameter[index] == Object[].class) {
                            match[index] = Object[].class;
                            if (method.getName().equals("visitFrame")) {
                                left.add(toConvertedParameter(builders.get(entry.getKey()).toTypeDescription(), Object[].class, FrameTranslator.NAME, index, true));
                                right.add(toConvertedParameter(builders.get(entry.getValue()).toTypeDescription(), Object[].class, FrameTranslator.NAME, index, true));
                            } else {
                                left.add(toConvertedParameter(builders.get(entry.getKey()).toTypeDescription(), Object[].class, ConstantArrayTranslator.NAME, index, false));
                                right.add(toConvertedParameter(builders.get(entry.getValue()).toTypeDescription(), Object[].class, ConstantArrayTranslator.NAME, index, false));
                            }
                        } else if (parameter[index] == Attribute.class) {
                            match[index] = utilities.get(Attribute.class);
                            unsupported = true;
                        } else {
                            match[index] = parameter[index];
                            left.add(new MethodCall.ArgumentLoader.ForMethodParameter.Factory(index));
                            right.add(new MethodCall.ArgumentLoader.ForMethodParameter.Factory(index));
                        }
                    }
                    Method target;
                    try {
                        target = entry.getValue().getMethod(method.getName(), match);
                    } catch (NoSuchMethodException ignored) {
                        target = null;
                        unsupported = true;
                    }
                    if (unsupported) {
{'fraction_non_alphanumeric': 0.10994509387176762, 'fraction_numerical': 0.000885582713425434, 'mean_word_length': 2.128983097811028, 'pattern_counts': {'":': 0, '<': 98, '<?xml version=': 0, '>': 96, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3957849', 'n_tokens_mistral': 5534, 'n_tokens_neox': 5342, 'n_words': 1013}