<commit_before>package jadx.core.utils;

import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.function.Function;

import org.jetbrains.annotations.Nullable;

import jadx.api.JadxDecompiler;
import jadx.core.codegen.CodeWriter;

public class Utils {

	public static final String JADX_API_PACKAGE = JadxDecompiler.class.getPackage().getName();

	private Utils() {
	}

	public static String cleanObjectName(String obj) {
		int last = obj.length() - 1;
		if (obj.charAt(0) == 'L' && obj.charAt(last) == ';') {
			return obj.substring(1, last).replace('/', '.');
		}
		return obj;
	}

	public static String makeQualifiedObjectName(String obj) {
		return 'L' + obj.replace('.', '/') + ';';
	}

	public static String listToString(Iterable<?> objects) {
		return listToString(objects, ", ");
	}

	public static String listToString(Iterable<?> objects, String joiner) {
		if (objects == null) {
			return "";
		}
		return listToString(objects, joiner, Object::toString);
	}

	public static <T> String listToString(Iterable<T> objects, Function<T, String> toStr) {
		return listToString(objects, ", ", toStr);
	}

	public static <T> String listToString(Iterable<T> objects, String joiner, Function<T, String> toStr) {
		StringBuilder sb = new StringBuilder();
		listToString(sb, objects, joiner, toStr);
		return sb.toString();
	}

	public static <T> void listToString(StringBuilder sb, Iterable<T> objects, String joiner, Function<T, String> toStr) {
		if (objects == null) {
			return;
		}
		Iterator<T> it = objects.iterator();
		if (it.hasNext()) {
			sb.append(toStr.apply(it.next()));
		}
		while (it.hasNext()) {
			sb.append(joiner).append(toStr.apply(it.next()));
		}
	}

	public static <T> String arrayToStr(T[] arr) {
		int len = arr == null ? 0 : arr.length;
		if (len == 0) {
			return "";
		}
		StringBuilder sb = new StringBuilder();
		sb.append(arr[0]);
		for (int i = 1; i < len; i++) {
			sb.append(", ").append(arr[i]);
		}
		return sb.toString();
	}

	public static String getStackTrace(Throwable throwable) {
		if (throwable == null) {
			return "";
		}
		StringWriter sw = new StringWriter();
		PrintWriter pw = new PrintWriter(sw, true);
		filterRecursive(throwable);
		throwable.printStackTrace(pw);
		return sw.getBuffer().toString();
	}

	public static void appendStackTrace(CodeWriter code, Throwable throwable) {
		if (throwable == null) {
			return;
		}
		code.startLine();
		OutputStream w = new OutputStream() {
			@Override
			public void write(int b) {
				char c = (char) b;
				switch (c) {
					case '\n':
						code.startLine();
						break;

					case '\r':
						// ignore
						break;

					default:
						code.add(c);
						break;
				}
			}
		};
		try (PrintWriter pw = new PrintWriter(w, true)) {
			filterRecursive(throwable);
			throwable.printStackTrace(pw);
			pw.flush();
		}
	}

	private static void filterRecursive(Throwable th) {
		try {
			filter(th);
		} catch (Exception e) {
			// ignore filter exceptions
		}
		Throwable cause = th.getCause();
		if (cause != null) {
			filterRecursive(cause);
		}
	}

	private static void filter(Throwable th) {
		StackTraceElement[] stackTrace = th.getStackTrace();
		int cutIndex = -1;
		int length = stackTrace.length;
		for (int i = 0; i < length; i++) {
			StackTraceElement stackTraceElement = stackTrace[i];
			if (stackTraceElement.getClassName().startsWith(JADX_API_PACKAGE)) {
				cutIndex = i;
			} else if (cutIndex > 0) {
				cutIndex = i;
				break;
			}
		}
		if (cutIndex > 0 && cutIndex < length) {
			th.setStackTrace(Arrays.copyOfRange(stackTrace, 0, cutIndex));
		}
	}<commit_msg>misc: show shorter exception stacktrace in code<commit_after>package jadx.core.utils;

import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.function.Function;

import org.jetbrains.annotations.Nullable;

import jadx.api.JadxDecompiler;
import jadx.core.codegen.CodeWriter;
import jadx.core.dex.visitors.DepthTraversal;

public class Utils {

	private static final String JADX_API_PACKAGE = JadxDecompiler.class.getPackage().getName();
	private static final String STACKTRACE_STOP_CLS_NAME = DepthTraversal.class.getName();

	private Utils() {
	}

	public static String cleanObjectName(String obj) {
		int last = obj.length() - 1;
		if (obj.charAt(0) == 'L' && obj.charAt(last) == ';') {
			return obj.substring(1, last).replace('/', '.');
		}
		return obj;
	}

	public static String makeQualifiedObjectName(String obj) {
		return 'L' + obj.replace('.', '/') + ';';
	}

	public static String listToString(Iterable<?> objects) {
		return listToString(objects, ", ");
	}

	public static String listToString(Iterable<?> objects, String joiner) {
		if (objects == null) {
			return "";
		}
		return listToString(objects, joiner, Object::toString);
	}

	public static <T> String listToString(Iterable<T> objects, Function<T, String> toStr) {
		return listToString(objects, ", ", toStr);
	}

	public static <T> String listToString(Iterable<T> objects, String joiner, Function<T, String> toStr) {
		StringBuilder sb = new StringBuilder();
		listToString(sb, objects, joiner, toStr);
		return sb.toString();
	}

	public static <T> void listToString(StringBuilder sb, Iterable<T> objects, String joiner, Function<T, String> toStr) {
		if (objects == null) {
			return;
		}
		Iterator<T> it = objects.iterator();
		if (it.hasNext()) {
			sb.append(toStr.apply(it.next()));
		}
		while (it.hasNext()) {
			sb.append(joiner).append(toStr.apply(it.next()));
		}
	}

	public static <T> String arrayToStr(T[] arr) {
		int len = arr == null ? 0 : arr.length;
		if (len == 0) {
			return "";
		}
		StringBuilder sb = new StringBuilder();
		sb.append(arr[0]);
		for (int i = 1; i < len; i++) {
			sb.append(", ").append(arr[i]);
		}
		return sb.toString();
	}

	public static String getStackTrace(Throwable throwable) {
		if (throwable == null) {
			return "";
		}
		StringWriter sw = new StringWriter();
		PrintWriter pw = new PrintWriter(sw, true);
		filterRecursive(throwable);
		throwable.printStackTrace(pw);
		return sw.getBuffer().toString();
	}

	public static void appendStackTrace(CodeWriter code, Throwable throwable) {
		if (throwable == null) {
			return;
		}
		code.startLine();
		OutputStream w = new OutputStream() {
			@Override
			public void write(int b) {
				char c = (char) b;
				switch (c) {
					case '\n':
						code.startLine();
						break;

					case '\r':
						// ignore
						break;

					default:
						code.add(c);
						break;
				}
			}
		};
		try (PrintWriter pw = new PrintWriter(w, true)) {
			filterRecursive(throwable);
			throwable.printStackTrace(pw);
			pw.flush();
		}
	}

	private static void filterRecursive(Throwable th) {
		try {
			filter(th);
		} catch (Exception e) {
			// ignore filter exceptions
		}
		Throwable cause = th.getCause();
		if (cause != null) {
			filterRecursive(cause);
		}
	}

	private static void filter(Throwable th) {
		StackTraceElement[] stackTrace = th.getStackTrace();
		int length = stackTrace.length;
		for (int i = 0; i < length; i++) {
			StackTraceElement stackTraceElement = stackTrace[i];
			String clsName = stackTraceElement.getClassName();
			if (clsName.equals(STACKTRACE_STOP_CLS_NAME)
					|| clsName.startsWith(JADX_API_PACKAGE)) {
				th.setStackTrace(Arrays.copyOfRange(stackTrace, 0, i));
				return;
			}
		}
	}
{'fraction_non_alphanumeric': 0.1426553672316384, 'fraction_numerical': 0.002696456086286595, 'mean_word_length': 3.755189255189255, 'pattern_counts': {'":': 0, '<': 34, '<?xml version=': 0, '>': 31, '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': '6640826', 'n_tokens_mistral': 2949, 'n_tokens_neox': 2594, 'n_words': 630}