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

import com.github.javaparser.JavaParser;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.body.TypeDeclaration;
import lombok.SneakyThrows;
import lombok.val;
import org.jetbrains.annotations.Nullable;

import java.io.*;
import java.nio.file.*;
import java.nio.file.attribute.*;
import java.util.*;
import java.util.zip.*;

// TODO: make this faster by using dumb regexes instead of JavaParser?
// probably not worth doing
public class SearchPath {
	final Map<String, String> classNameToPath = new HashMap<>();
	final List<Path> inputPaths;

	@SneakyThrows
	public SearchPath(List<Path> paths) {
		inputPaths = paths;
		for (Path path : paths)
			if (Files.isDirectory(path))
				Files.walkFileTree(path, new SimpleFileVisitor<Path>() {
					@Override
					public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
						val entryName = path.relativize(file).toString().replace(File.separatorChar, '/');
						if (entryName.endsWith(".java")) {
							val parsed = JavaParser.parse(file);
							findPaths(entryName, parsed);
						}
						return super.visitFile(file, attrs);
					}
				});
			else if (Files.isRegularFile(path))
				try (val zis = new ZipInputStream(Files.newInputStream(path))) {
					ZipEntry e;
					while ((e = zis.getNextEntry()) != null)
						findPaths(e, zis);
				}
	}

	private void findPaths(ZipEntry e, ZipInputStream zis) {
		val entryName = e.getName();
		if (!e.getName().endsWith(".java"))
			return;
		val parsed = JavaParser.parse(zis);
		findPaths(entryName, parsed);
	}

	private void findPaths(String path, CompilationUnit compilationUnit) {
		val typeNames = compilationUnit.getTypes();
		val packageDeclaration = compilationUnit.getPackageDeclaration().orElse(null);
		val prefix = packageDeclaration == null ? "" : packageDeclaration.getNameAsString() + '.';
		for (TypeDeclaration<?> typeDeclaration : typeNames)
			findPaths(path, typeDeclaration, prefix);
	}

	private void findPaths(String path, TypeDeclaration<?> typeDeclaration, String packagePrefix) {
		val parent = typeDeclaration.getParentNode().orElse(null);
		String name;
		if (parent instanceof TypeDeclaration)
			name = packagePrefix + ((TypeDeclaration) parent).getNameAsString() + '.' + typeDeclaration.getNameAsString();
		else
			name = packagePrefix + typeDeclaration.getNameAsString();
		classNameToPath.put(name, path);
	}

	@Override
	public String toString() {
		return "SearchPath: " + inputPaths;
	}

	public boolean hasClass(String className) {
		return classNameToPath.containsKey(className);
	}

	@Nullable
	public String getPathForClass(String className) {
		return classNameToPath.get(className);
	}
}
<commit_msg>Pass an InputStream which can't be closed to JavaParser in SearchPath<commit_after>package org.minimallycorrect.javatransformer.internal;

import com.github.javaparser.JavaParser;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.body.TypeDeclaration;
import lombok.SneakyThrows;
import lombok.val;
import org.jetbrains.annotations.Nullable;

import java.io.*;
import java.nio.file.*;
import java.nio.file.attribute.*;
import java.util.*;
import java.util.zip.*;

// TODO: make this faster by using dumb regexes instead of JavaParser?
// probably not worth doing
public class SearchPath {
	final Map<String, String> classNameToPath = new HashMap<>();
	final List<Path> inputPaths;

	@SneakyThrows
	public SearchPath(List<Path> paths) {
		inputPaths = paths;
		for (Path path : paths)
			if (Files.isDirectory(path))
				Files.walkFileTree(path, new SimpleFileVisitor<Path>() {
					@Override
					public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
						val entryName = path.relativize(file).toString().replace(File.separatorChar, '/');
						if (entryName.endsWith(".java")) {
							val parsed = JavaParser.parse(file);
							findPaths(entryName, parsed);
						}
						return super.visitFile(file, attrs);
					}
				});
			else if (Files.isRegularFile(path))
				try (val zis = new ZipInputStream(Files.newInputStream(path))) {
					ZipEntry e;
					while ((e = zis.getNextEntry()) != null) {
						findPaths(e, zis);
						zis.closeEntry();
					}
				}
	}

	private void findPaths(ZipEntry e, ZipInputStream zis) {
		val entryName = e.getName();
		if (!e.getName().endsWith(".java"))
			return;
		val parsed = JavaParser.parse(new InputStream() {
			public int read(byte[] b, int off, int len) throws IOException {
				return zis.read(b, off, len);
			}

			public void close() throws IOException {
			}

			public int read() throws IOException {
				return zis.read();
			}
		});
		findPaths(entryName, parsed);
	}

	private void findPaths(String path, CompilationUnit compilationUnit) {
		val typeNames = compilationUnit.getTypes();
		val packageDeclaration = compilationUnit.getPackageDeclaration().orElse(null);
		val prefix = packageDeclaration == null ? "" : packageDeclaration.getNameAsString() + '.';
		for (TypeDeclaration<?> typeDeclaration : typeNames)
			findPaths(path, typeDeclaration, prefix);
	}

	private void findPaths(String path, TypeDeclaration<?> typeDeclaration, String packagePrefix) {
		val parent = typeDeclaration.getParentNode().orElse(null);
		String name;
		if (parent instanceof TypeDeclaration)
			name = packagePrefix + ((TypeDeclaration) parent).getNameAsString() + '.' + typeDeclaration.getNameAsString();
		else
			name = packagePrefix + typeDeclaration.getNameAsString();
		classNameToPath.put(name, path);
	}

	@Override
	public String toString() {
		return "SearchPath: " + inputPaths;
	}

	public boolean hasClass(String className) {
		return classNameToPath.containsKey(className);
	}

	@Nullable
	public String getPathForClass(String className) {
		return classNameToPath.get(className);
	}
}

{'fraction_non_alphanumeric': 0.11823579304495335, 'fraction_numerical': 0.0, 'mean_word_length': 4.505135387488329, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 17, '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': '6722889', 'n_tokens_mistral': 1975, 'n_tokens_neox': 1717, 'n_words': 424}