Skip to content

Commit

Permalink
graaaah
Browse files Browse the repository at this point in the history
  • Loading branch information
ix0rai committed Sep 17, 2024
1 parent 6c3842f commit 4a1a27c
Show file tree
Hide file tree
Showing 16 changed files with 139 additions and 86 deletions.
26 changes: 9 additions & 17 deletions enigma/src/main/java/org/quiltmc/enigma/api/Enigma.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import org.quiltmc.enigma.api.analysis.index.jar.LibrariesJarIndex;
import org.quiltmc.enigma.api.analysis.index.jar.MainJarIndex;
import org.quiltmc.enigma.api.analysis.index.mapping.MappingsIndex;
import org.quiltmc.enigma.api.class_provider.ProjectClassProvider;
import org.quiltmc.enigma.impl.analysis.ClassLoaderClassProvider;
import org.quiltmc.enigma.api.service.EnigmaService;
import org.quiltmc.enigma.api.service.EnigmaServiceContext;
Expand Down Expand Up @@ -43,13 +44,11 @@
import java.sql.DriverManager;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Properties;
import java.util.ServiceLoader;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;

public class Enigma {
Expand Down Expand Up @@ -85,14 +84,10 @@ public EnigmaProject openJar(Path path, ClassProvider libraryClassProvider, Prog
ClassLoaderClassProvider jreProvider = new ClassLoaderClassProvider(DriverManager.class.getClassLoader());
CombiningClassProvider librariesProvider = new CombiningClassProvider(jreProvider, libraryClassProvider);
ClassProvider mainProjectProvider = new ObfuscationFixClassProvider(new CachingClassProvider(jarClassProvider), index);

Set<String> mainScope = new HashSet<>(mainProjectProvider.getClassNames());
Set<String> librariesScope = new HashSet<>(librariesProvider.getClassNames());
ProjectClassProvider projectClassProvider = new ProjectClassProvider(mainProjectProvider, librariesProvider);

// main index
this.index(index, mainProjectProvider, mainScope, progress, false);
// lib index
this.index(libIndex, librariesProvider, librariesScope, progress, true);
this.index(index, projectClassProvider, progress);

// name proposal
var nameProposalServices = this.getNameProposalServices();
Expand Down Expand Up @@ -124,22 +119,19 @@ public EnigmaProject openJar(Path path, ClassProvider libraryClassProvider, Prog
return new EnigmaProject(this, path, mainProjectProvider, index, libIndex, mappingsIndex, proposedNames, Utils.zipSha1(path));
}

private void index(JarIndex index, ClassProvider classProvider, Set<String> scope, ProgressListener progress, boolean libraries) {
String progressKey = libraries ? "libs" : "jar";
index.indexJar(scope, classProvider, progress);
private void index(JarIndex index, ProjectClassProvider classProvider, ProgressListener progress) {
index.indexJar(classProvider, progress);

List<JarIndexerService> indexers = this.services.get(JarIndexerService.TYPE);
progress.init(indexers.size(), I18n.translate("progress." + progressKey + ".custom_indexing"));
progress.init(indexers.size(), I18n.translate("progress.jar.custom_indexing"));

int i = 1;
for (var service : indexers) {
if (!(libraries && !service.shouldIndexLibraries())) {
progress.step(i++, I18n.translateFormatted("progress." + progressKey + ".custom_indexing.indexer", service.getId()));
service.acceptJar(scope, classProvider, index);
}
progress.step(i++, I18n.translateFormatted("progress.jar.custom_indexing.indexer", service.getId()));
service.acceptJar(classProvider, index);
}

progress.step(i, I18n.translate("progress." + progressKey + ".custom_indexing.finished"));
progress.step(i, I18n.translate("progress.jar.custom_indexing.finished"));
}

public EnigmaProfile getProfile() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,11 @@

import com.google.common.collect.ListMultimap;
import org.quiltmc.enigma.api.ProgressListener;
import org.quiltmc.enigma.api.class_provider.ClassProvider;
import org.quiltmc.enigma.api.class_provider.ProjectClassProvider;
import org.quiltmc.enigma.api.translation.mapping.EntryResolver;
import org.quiltmc.enigma.api.translation.representation.entry.ClassEntry;
import org.quiltmc.enigma.api.translation.representation.entry.ParentedEntry;

import java.util.Set;

public interface JarIndex extends JarIndexer {
/**
* Gets the index associated with the provided class.
Expand All @@ -19,11 +17,10 @@ public interface JarIndex extends JarIndexer {

/**
* Runs every configured indexer over the provided jar.
* @param classNames the obfuscated names of each class in the jar
* @param classProvider a class provider containing all classes in the jar
* @param classProvider a class provider containing all classes in the jar and libraries
* @param progress a progress listener to track index completion
*/
void indexJar(Set<String> classNames, ClassProvider classProvider, ProgressListener progress);
void indexJar(ProjectClassProvider classProvider, ProgressListener progress);

/**
* {@return an entry resolver with this index's contents as context}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package org.quiltmc.enigma.api.analysis.index.jar;

import org.quiltmc.enigma.api.ProgressListener;
import org.quiltmc.enigma.api.class_provider.ProjectClassProvider;
import org.quiltmc.enigma.impl.analysis.index.AbstractJarIndex;

public class LibrariesJarIndex extends AbstractJarIndex {
Expand All @@ -22,4 +24,9 @@ public static JarIndex empty() {
public String getTranslationKey() {
return "progress.jar.indexing.libraries";
}

@Override
public void indexJar(ProjectClassProvider classProvider, ProgressListener progress) {
this.indexJar(classProvider.getLibraryClassNames(), classProvider, progress);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package org.quiltmc.enigma.api.analysis.index.jar;

import org.quiltmc.enigma.api.ProgressListener;
import org.quiltmc.enigma.api.class_provider.ProjectClassProvider;
import org.quiltmc.enigma.impl.analysis.index.AbstractJarIndex;

public class MainJarIndex extends AbstractJarIndex {
Expand All @@ -26,4 +28,9 @@ public static JarIndex empty() {
public String getTranslationKey() {
return "progress.jar.indexing.jar";
}

@Override
public void indexJar(ProjectClassProvider classProvider, ProgressListener progress) {
this.indexJar(classProvider.getMainClassNames(), classProvider, progress);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public ObfuscationFixClassProvider(ClassProvider classProvider, JarIndex jarInde
public ClassNode get(String name) {
ClassNode node = this.classProvider.get(name);

if (!this.jarIndex.isIndexed(name)) {
if (!this.jarIndex.isIndexed(name) || node == null) {
return node;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package org.quiltmc.enigma.api.class_provider;

import org.objectweb.asm.tree.ClassNode;

import javax.annotation.Nullable;
import java.security.InvalidParameterException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;

public class ProjectClassProvider implements ClassProvider {
@Nullable
private final ClassProvider main;
@Nullable
private final ClassProvider libraries;
private final Collection<String> classNames;

public ProjectClassProvider(@Nullable ClassProvider main, @Nullable ClassProvider libraries) {
if (main == null && libraries == null) {
throw new InvalidParameterException("cannot create a project class provider with both main and library providers as null!");
}

this.main = main;
this.libraries = libraries;
this.classNames = new ArrayList<>();
if (main != null) {
this.classNames.addAll(main.getClassNames());
}

if (libraries != null) {
this.classNames.addAll(libraries.getClassNames());
}
}

@Nullable
@Override
public ClassNode get(String name) {
// i hate working with nullability and am a bad programmer. btw
ClassNode mainNode;
if (this.main != null) {
mainNode = this.main.get(name);
if (mainNode != null) {
return mainNode;
}
}

if (this.libraries != null) {
return this.libraries.get(name);
}

return null;
}

/**
* Gets the {@linkplain ClassNode} for a class in the main JAR file. The class provider may return a cached result,
* so it's important to not mutate it.
*
* @param name the internal name of the class
* @return the {@linkplain ClassNode} for that class, or {@code null} if it was not found
*/
public ClassNode getMainClass(String name) {
return this.main != null ? this.main.get(name) : null;
}

/**
* Gets the {@linkplain ClassNode} for a class in the provided libraries. The class provider may return a cached result,
* so it's important to not mutate it.
*
* @param name the internal name of the class
* @return the {@linkplain ClassNode} for that class, or {@code null} if it was not found
*/
public ClassNode getLibraryClass(String name) {
return this.libraries != null ? this.libraries.get(name) : null;
}

@Override
public Collection<String> getClassNames() {
return this.classNames;
}

public Collection<String> getMainClassNames() {
return this.main != null ? this.main.getClassNames() : new HashSet<>();
}

public Collection<String> getLibraryClassNames() {
return this.libraries != null ? this.libraries.getClassNames() : new HashSet<>();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,8 @@

import org.objectweb.asm.tree.ClassNode;
import org.quiltmc.enigma.api.analysis.index.jar.JarIndex;
import org.quiltmc.enigma.api.class_provider.ClassProvider;
import org.objectweb.asm.ClassVisitor;

import javax.annotation.Nullable;
import java.util.Set;
import org.quiltmc.enigma.api.class_provider.ProjectClassProvider;

/**
* Jar indexer services analyse jar files as they're opened to collect information about their contents.
Expand All @@ -16,35 +13,12 @@
public interface JarIndexerService extends EnigmaService {
EnigmaServiceType<JarIndexerService> TYPE = EnigmaServiceType.create("jar_indexer");

/**
* Checks the {@code index_libraries} argument in the context to determine if libraries should be indexed.
* @param context the context for this service
* @return whether libraries should be indexed
*/
static boolean shouldIndexLibraries(@Nullable EnigmaServiceContext<JarIndexerService> context) {
if (context == null) {
return false;
}

return context.getSingleArgument("index_libraries").map(Boolean::parseBoolean).orElse(false);
}

/**
* Indexes a collection of classes.
* @param scope a list of class names to be indexed
* @param classProvider a provider to translate class names into {@link ClassNode class nodes}
* @param classProvider a provider to translate class names into {@link ClassNode class nodes}.
* @param jarIndex the current jar index
*/
void acceptJar(Set<String> scope, ClassProvider classProvider, JarIndex jarIndex);

/**
* Whether this indexer should be run on libraries in addition to the main project being indexed.
* @implNote implementations should use {@link #shouldIndexLibraries(EnigmaServiceContext)} to allow changing this setting via the {@link org.quiltmc.enigma.api.EnigmaProfile profile}
* @return whether this indexer should target libraries
*/
default boolean shouldIndexLibraries() {
return false;
}
void acceptJar(ProjectClassProvider classProvider, JarIndex jarIndex);

/**
* Creates an indexer service that runs all {@link ClassNode class nodes} through the provided {@link ClassVisitor visitor}.
Expand All @@ -53,24 +27,10 @@ default boolean shouldIndexLibraries() {
* @return the indexer service
*/
static JarIndexerService fromVisitor(ClassVisitor visitor, String id) {
return fromVisitor(null, visitor, id);
}

/**
* Creates an indexer service that runs all {@link ClassNode class nodes} through the provided {@link ClassVisitor visitor}.
* Overrides {@link #shouldIndexLibraries()} according to the profile argument described in {@link #shouldIndexLibraries(EnigmaServiceContext)}.
* @param context the profile context for the service
* @param visitor the visitor to pass classes through
* @param id the service's ID
* @return the indexer service
*/
static JarIndexerService fromVisitor(@Nullable EnigmaServiceContext<JarIndexerService> context, ClassVisitor visitor, String id) {
boolean indexLibs = shouldIndexLibraries(context);

return new JarIndexerService() {
@Override
public void acceptJar(Set<String> scope, ClassProvider classProvider, JarIndex jarIndex) {
for (String className : scope) {
public void acceptJar(ProjectClassProvider classProvider, JarIndex jarIndex) {
for (String className : classProvider.getClassNames()) {
ClassNode node = classProvider.get(className);
if (node != null) {
node.accept(visitor);
Expand All @@ -82,11 +42,6 @@ public void acceptJar(Set<String> scope, ClassProvider classProvider, JarIndex j
public String getId() {
return id;
}

@Override
public boolean shouldIndexLibraries() {
return indexLibs;
}
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import org.quiltmc.enigma.api.translation.representation.entry.ParentedEntry;
import org.quiltmc.enigma.util.I18n;

import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
Expand Down Expand Up @@ -72,11 +73,10 @@ public <T extends JarIndexer> T getIndex(Class<T> clazz) {

/**
* Runs every configured indexer over the provided jar.
* @param classNames the obfuscated names of each class in the jar
* @param classProvider a class provider containing all classes in the jar
* @param progress a progress listener to track index completion
*/
public void indexJar(Set<String> classNames, ClassProvider classProvider, ProgressListener progress) {
public void indexJar(Collection<String> classNames, ClassProvider classProvider, ProgressListener progress) {
// for use in processIndex
this.progress = progress;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ private static void registerEnumNamingService(EnigmaPluginContext ctx) {
final Map<Entry<?>, String> names = new HashMap<>();
final EnumFieldNameFindingVisitor visitor = new EnumFieldNameFindingVisitor(names);

ctx.registerService(JarIndexerService.TYPE, ctx1 -> JarIndexerService.fromVisitor(ctx1, visitor, "enigma:enum_initializer_indexer"));
ctx.registerService(JarIndexerService.TYPE, ctx1 -> JarIndexerService.fromVisitor(visitor, "enigma:enum_initializer_indexer"));

ctx.registerService(NameProposalService.TYPE, ctx1 -> new NameProposalService() {
@Override
Expand Down Expand Up @@ -66,7 +66,7 @@ private static void registerRecordNamingService(EnigmaPluginContext ctx) {
final Map<FieldEntry, MethodEntry> fieldToGetter = new HashMap<>();
final RecordGetterFindingVisitor visitor = new RecordGetterFindingVisitor(fieldToGetter);

ctx.registerService(JarIndexerService.TYPE, ctx1 -> JarIndexerService.fromVisitor(ctx1, visitor, "enigma:record_component_indexer"));
ctx.registerService(JarIndexerService.TYPE, ctx1 -> JarIndexerService.fromVisitor(visitor, "enigma:record_component_indexer"));
ctx.registerService(NameProposalService.TYPE, ctx1 -> new RecordComponentProposalService(fieldToGetter));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
import org.quiltmc.enigma.api.analysis.index.jar.MainJarIndex;
import org.quiltmc.enigma.api.analysis.index.jar.PackageVisibilityIndex;
import org.quiltmc.enigma.api.ProgressListener;
import org.quiltmc.enigma.api.class_provider.CachingClassProvider;
import org.quiltmc.enigma.api.class_provider.JarClassProvider;
import org.quiltmc.enigma.api.class_provider.ProjectClassProvider;
import org.quiltmc.enigma.api.translation.representation.entry.ClassEntry;
import org.junit.jupiter.api.Test;

Expand All @@ -27,7 +29,7 @@ public class PackageVisibilityIndexTest {
public PackageVisibilityIndexTest() throws Exception {
JarClassProvider jcp = new JarClassProvider(JAR);
this.jarIndex = MainJarIndex.empty();
this.jarIndex.indexJar(jcp.getClassNames(), jcp, ProgressListener.createEmpty());
this.jarIndex.indexJar(new ProjectClassProvider(new CachingClassProvider(jcp), null), ProgressListener.createEmpty());
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import org.quiltmc.enigma.api.analysis.index.jar.MainJarIndex;
import org.quiltmc.enigma.api.class_provider.CachingClassProvider;
import org.quiltmc.enigma.api.class_provider.JarClassProvider;
import org.quiltmc.enigma.api.class_provider.ProjectClassProvider;
import org.quiltmc.enigma.api.source.Decompiler;
import org.quiltmc.enigma.api.source.Decompilers;
import org.quiltmc.enigma.api.source.SourceSettings;
Expand Down Expand Up @@ -34,7 +35,7 @@ public TestInnerClasses() throws Exception {
JarClassProvider jcp = new JarClassProvider(JAR);
CachingClassProvider classProvider = new CachingClassProvider(jcp);
this.index = MainJarIndex.empty();
this.index.indexJar(jcp.getClassNames(), classProvider, ProgressListener.createEmpty());
this.index.indexJar(new ProjectClassProvider(classProvider, null), ProgressListener.createEmpty());
this.decompiler = Decompilers.CFR.create(classProvider, new SourceSettings(false, false));
}

Expand Down
Loading

0 comments on commit 4a1a27c

Please sign in to comment.