<commit_before>package org.minimallycorrect.mixin.internal;

import lombok.*;
import me.nallar.whocalled.WhoCalled;
import org.minimallycorrect.javatransformer.api.*;
import org.minimallycorrect.javatransformer.internal.SimpleMethodInfo;
import org.minimallycorrect.mixin.*;

import java.nio.file.*;
import java.util.*;
import java.util.function.*;
import java.util.stream.*;

@SuppressWarnings("CodeBlock2Expr")
@Data
public class MixinApplicator {
	private static final Map<String, List<IndexedAnnotationApplier<? extends ClassMember>>> consumerMap = new HashMap<>();
	private static final Map<Path, List<String>> sources = new HashMap<>();

	static {
		addAnnotationHandler(ClassInfo.class, Mixin.class, Integer.MIN_VALUE, (applicator, annotation, member, target) -> {
			applicator.logInfo("Handling class " + member.getName() + " with annotation " + annotation);
		});

		addAnnotationHandler(ClassInfo.class, Mixin.class, 1, (applicator, annotation, member, target) -> {
			if (applicator.applicationType == ApplicationType.FINAL_PATCH)
				return;

			// Add no-args protected constructor if there are existing constructors and none of them are no-args
			val constructors = target.getConstructors().collect(Collectors.toList());
			if (!constructors.isEmpty() && constructors.stream().noneMatch(it -> it.getParameters().isEmpty())) {
				target.add(SimpleMethodInfo.of(new AccessFlags(AccessFlags.ACC_PROTECTED), Collections.emptyList(), target.getType(), "<init>", Collections.emptyList()));
			}

			boolean makePublic = annotation.makePublic();

			target.accessFlags((f) -> f.makeAccessible(makePublic).without(AccessFlags.ACC_FINAL));
			target.getMembers().forEach(it -> it.accessFlags(f -> f.makeAccessible(makePublic).without(AccessFlags.ACC_FINAL | AccessFlags.ACC_SYNTHETIC)));
		});

		addAnnotationHandler(FieldInfo.class, Add.class, (applicator, annotation, member, target) -> {
			String name = member.getName();
			if (!name.endsWith("_"))
				throw new MixinError("Name of @Add-ed field must end with '_'");

			target.add(member);
			target.get(member).setName(name.substring(0, name.length() - 1));
		});

		addAnnotationHandler(MethodInfo.class, Add.class, (applicator, annotation, member, target) -> {
			target.add(member);
		});

		addAnnotationHandler(MethodInfo.class, Overwrite.class, (applicator, annotation, member, target) -> {
			val existing = get(member, target);

			if (applicator.applicationType == ApplicationType.PRE_PATCH)
				return;

			target.remove(existing);
			target.add(member);
		});

		addAnnotationHandler(MethodInfo.class, Synchronize.class, (applicator, annotation, member, target) -> {
			target.get(member).accessFlags(it -> it.with(AccessFlags.ACC_SYNCHRONIZED));
		});

		addAnnotationHandler(MethodInfo.class, Inject.class, (applicator, annotation, member, target) -> {
			val injectableName = annotation.injectable();
			val injectableMethods = member.getClassInfo().getMethods().filter(it -> {
				val injectables = it.getAnnotations(Injectable.class.getName());
				if (injectables.isEmpty())
					return false;
				String thisInjectableName = (String) injectables.get(0).values.get("name");
				if (thisInjectableName == null)
					thisInjectableName = "";
				return (it.getName().equals(injectableName) && thisInjectableName.equals("")) || it.getName().equals(thisInjectableName);
			}).collect(Collectors.toList());

			if (injectableMethods.size() != 1)
				throw new MixinError("Couldn't find exactly 1 injectable with name " + injectableName + " in " + member.getClassInfo().getName());

			Injector.inject(get(member, target), injectableMethods.get(0), annotation);
		});
	}

	private final List<TargetedTransformer> transformers = new ArrayList<>();
	private Consumer<String> log = System.out::println;
	private boolean noMixinIsError = false;
	private boolean notAppliedIsError = true;
	private ApplicationType applicationType = ApplicationType.FINAL_PATCH;
	@Getter(AccessLevel.NONE)
	@Setter(AccessLevel.NONE)
	private JavaTransformer transformer;

	@NonNull
	private static MethodInfo get(MethodInfo from, ClassInfo target) {
		val existing = target.get(from);
		if (existing == null)
			throw new MixinError("Can't find injectable matching " + from + " in target " + target + "\nMethods in target: " + target.getMethods());
		return existing;
	}

	private static void addAnnotationHandler(IndexedAnnotationApplier<?> applier, String name) {
		if (!name.contains("."))
			name = "org.minimallycorrect.mixin." + name;
		consumerMap.computeIfAbsent(name, k -> new ArrayList<>()).add(applier);
	}

	private static void addAnnotationHandler(AnnotationApplier<?> applier, int index, String... names) {
		for (String name : names)
			addAnnotationHandler(new IndexedAnnotationApplier<>(index, applier), name);
	}

	@SuppressWarnings("unchecked")
	private static <T extends ClassMember> void addAnnotationHandler(Class<T> clazz, int index, AnnotationApplier<T> applier, String... names) {
		addAnnotationHandler((applicator, annotation, member, target) -> {
			if (clazz.isAssignableFrom(member.getClass()))
				applier.apply(applicator, annotation, (T) member, target);<commit_msg>Use Collectors.toList() when a method can't be found to improve debug logging<commit_after>package org.minimallycorrect.mixin.internal;

import lombok.*;
import me.nallar.whocalled.WhoCalled;
import org.minimallycorrect.javatransformer.api.*;
import org.minimallycorrect.javatransformer.internal.SimpleMethodInfo;
import org.minimallycorrect.mixin.*;

import java.nio.file.*;
import java.util.*;
import java.util.function.*;
import java.util.stream.*;

@SuppressWarnings("CodeBlock2Expr")
@Data
public class MixinApplicator {
	private static final Map<String, List<IndexedAnnotationApplier<? extends ClassMember>>> consumerMap = new HashMap<>();
	private static final Map<Path, List<String>> sources = new HashMap<>();

	static {
		addAnnotationHandler(ClassInfo.class, Mixin.class, Integer.MIN_VALUE, (applicator, annotation, member, target) -> {
			applicator.logInfo("Handling class " + member.getName() + " with annotation " + annotation);
		});

		addAnnotationHandler(ClassInfo.class, Mixin.class, 1, (applicator, annotation, member, target) -> {
			if (applicator.applicationType == ApplicationType.FINAL_PATCH)
				return;

			// Add no-args protected constructor if there are existing constructors and none of them are no-args
			val constructors = target.getConstructors().collect(Collectors.toList());
			if (!constructors.isEmpty() && constructors.stream().noneMatch(it -> it.getParameters().isEmpty())) {
				target.add(SimpleMethodInfo.of(new AccessFlags(AccessFlags.ACC_PROTECTED), Collections.emptyList(), target.getType(), "<init>", Collections.emptyList()));
			}

			boolean makePublic = annotation.makePublic();

			target.accessFlags((f) -> f.makeAccessible(makePublic).without(AccessFlags.ACC_FINAL));
			target.getMembers().forEach(it -> it.accessFlags(f -> f.makeAccessible(makePublic).without(AccessFlags.ACC_FINAL | AccessFlags.ACC_SYNTHETIC)));
		});

		addAnnotationHandler(FieldInfo.class, Add.class, (applicator, annotation, member, target) -> {
			String name = member.getName();
			if (!name.endsWith("_"))
				throw new MixinError("Name of @Add-ed field must end with '_'");

			target.add(member);
			target.get(member).setName(name.substring(0, name.length() - 1));
		});

		addAnnotationHandler(MethodInfo.class, Add.class, (applicator, annotation, member, target) -> {
			target.add(member);
		});

		addAnnotationHandler(MethodInfo.class, Overwrite.class, (applicator, annotation, member, target) -> {
			val existing = get(member, target);

			if (applicator.applicationType == ApplicationType.PRE_PATCH)
				return;

			target.remove(existing);
			target.add(member);
		});

		addAnnotationHandler(MethodInfo.class, Synchronize.class, (applicator, annotation, member, target) -> {
			target.get(member).accessFlags(it -> it.with(AccessFlags.ACC_SYNCHRONIZED));
		});

		addAnnotationHandler(MethodInfo.class, Inject.class, (applicator, annotation, member, target) -> {
			val injectableName = annotation.injectable();
			val injectableMethods = member.getClassInfo().getMethods().filter(it -> {
				val injectables = it.getAnnotations(Injectable.class.getName());
				if (injectables.isEmpty())
					return false;
				String thisInjectableName = (String) injectables.get(0).values.get("name");
				if (thisInjectableName == null)
					thisInjectableName = "";
				return (it.getName().equals(injectableName) && thisInjectableName.equals("")) || it.getName().equals(thisInjectableName);
			}).collect(Collectors.toList());

			if (injectableMethods.size() != 1)
				throw new MixinError("Couldn't find exactly 1 injectable with name " + injectableName + " in " + member.getClassInfo().getName());

			Injector.inject(get(member, target), injectableMethods.get(0), annotation);
		});
	}

	private final List<TargetedTransformer> transformers = new ArrayList<>();
	private Consumer<String> log = System.out::println;
	private boolean noMixinIsError = false;
	private boolean notAppliedIsError = true;
	private ApplicationType applicationType = ApplicationType.FINAL_PATCH;
	@Getter(AccessLevel.NONE)
	@Setter(AccessLevel.NONE)
	private JavaTransformer transformer;

	@NonNull
	private static MethodInfo get(MethodInfo from, ClassInfo target) {
		val existing = target.get(from);
		if (existing == null)
			throw new MixinError("Can't find method matching " + from + " in target " + target + "\nMethods in target: " + target.getMethods().collect(Collectors.toList()));
		return existing;
	}

	private static void addAnnotationHandler(IndexedAnnotationApplier<?> applier, String name) {
		if (!name.contains("."))
			name = "org.minimallycorrect.mixin." + name;
		consumerMap.computeIfAbsent(name, k -> new ArrayList<>()).add(applier);
	}

	private static void addAnnotationHandler(AnnotationApplier<?> applier, int index, String... names) {
		for (String name : names)
			addAnnotationHandler(new IndexedAnnotationApplier<>(index, applier), name);
	}

	@SuppressWarnings("unchecked")
	private static <T extends ClassMember> void addAnnotationHandler(Class<T> clazz, int index, AnnotationApplier<T> applier, String... names) {
		addAnnotationHandler((applicator, annotation, member, target) -> {
			if (clazz.isAssignableFrom(member.getClass()))
				applier.apply(applicator, annotation, (T) member, target);
{'fraction_non_alphanumeric': 0.1363854958161008, 'fraction_numerical': 0.0015389054534962008, 'mean_word_length': 5.406654343807763, 'pattern_counts': {'":': 0, '<': 39, '<?xml version=': 0, '>': 69, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, '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': '1794102', 'n_tokens_mistral': 3332, 'n_tokens_neox': 3018, 'n_words': 664}