Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -124,10 +124,10 @@ public static void main(String[] args) {

EntryRemapper mappings;
if (!Files.exists(mappingsFile)) {
mappings = EntryRemapper.mapped(enigma, project.getCombinedIndex(), project.getMappingsIndex(), project.getRemapper().getJarProposedMappings(), new HashEntryTree<>(), enigma.getNameProposalServices());
mappings = EntryRemapper.mapped(project, project.getRemapper().getJarProposedMappings(), new HashEntryTree<>());
} else {
Logger.info("Reading mappings...");
mappings = EntryRemapper.mapped(enigma, project.getCombinedIndex(), project.getMappingsIndex(), project.getRemapper().getJarProposedMappings(), readWriteService.get().read(mappingsFile), enigma.getNameProposalServices());
mappings = EntryRemapper.mapped(project, project.getRemapper().getJarProposedMappings(), readWriteService.get().read(mappingsFile));
}

PrintWriter log = new PrintWriter(Files.newBufferedWriter(logFile));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -686,7 +686,7 @@ public void createClient(String username, String ip, int port, char[] password)
}

public void createServer(String username, int port, char[] password) throws IOException {
this.server = new IntegratedEnigmaServer(this.project.getJarChecksum(), password, EntryRemapper.mapped(this.project.getEnigma(), this.project.getCombinedIndex(), this.project.getMappingsIndex(), new HashEntryTree<>(this.project.getRemapper().getJarProposedMappings()), new HashEntryTree<>(this.project.getRemapper().getDeobfMappings()), this.project.getEnigma().getNameProposalServices()), port);
this.server = new IntegratedEnigmaServer(this.project.getJarChecksum(), password, EntryRemapper.mapped(this.project, new HashEntryTree<>(this.project.getRemapper().getJarProposedMappings()), new HashEntryTree<>(this.project.getRemapper().getDeobfMappings())), port);
this.server.start();
this.client = new IntegratedEnigmaClient(this, "127.0.0.1", port);
this.client.connect();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ public EnigmaProject(Enigma enigma, Path jarPath, ClassProvider classProvider, J
this.jarChecksum = jarChecksum;

this.mappingsIndex = mappingsIndex;
this.remapper = EntryRemapper.mapped(this.enigma, this.combinedIndex, this.mappingsIndex, proposedNames, new HashEntryTree<>(), this.enigma.getNameProposalServices());
this.remapper = EntryRemapper.mapped(this, proposedNames, new HashEntryTree<>());
}

/**
Expand All @@ -97,12 +97,12 @@ public void setMappings(@Nullable EntryTree<EntryMapping> mappings, ProgressList
EntryTree<EntryMapping> mergedTree = EntryTreeUtil.merge(jarProposedMappings, mappings);

this.mappingsIndex.indexMappings(mergedTree, progress);
this.remapper = EntryRemapper.mapped(this.enigma, this.combinedIndex, this.mappingsIndex, jarProposedMappings, mappings, this.enigma.getNameProposalServices());
this.remapper = EntryRemapper.mapped(this, jarProposedMappings, mappings);
} else if (!jarProposedMappings.isEmpty()) {
this.mappingsIndex.indexMappings(jarProposedMappings, progress);
this.remapper = EntryRemapper.mapped(this.enigma, this.combinedIndex, this.mappingsIndex, jarProposedMappings, new HashEntryTree<>(), this.enigma.getNameProposalServices());
this.remapper = EntryRemapper.mapped(this, jarProposedMappings, new HashEntryTree<>());
} else {
this.remapper = EntryRemapper.empty(this.enigma, this.combinedIndex, this.enigma.getNameProposalServices());
this.remapper = EntryRemapper.empty(this);
}

// update dynamically proposed names
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import org.jspecify.annotations.NonNull;
import org.jspecify.annotations.Nullable;
import org.quiltmc.enigma.api.Enigma;
import org.quiltmc.enigma.api.EnigmaProject;
import org.quiltmc.enigma.api.analysis.index.jar.InheritanceIndex;
import org.quiltmc.enigma.api.analysis.index.jar.JarIndex;
import org.quiltmc.enigma.api.analysis.index.mapping.MappingsIndex;
Expand Down Expand Up @@ -30,7 +31,7 @@
import java.util.Set;
import java.util.stream.Stream;

public class EntryRemapper {
public final class EntryRemapper {
private final EntryTree<EntryMapping> deobfMappings;
private final EntryTree<EntryMapping> jarProposedMappings;
private final EntryTree<EntryMapping> proposedMappings;
Expand All @@ -45,7 +46,12 @@ public class EntryRemapper {
private final MappingValidator validator;
private final List<NameProposalService> proposalServices;

private EntryRemapper(Enigma enigma, JarIndex jarIndex, MappingsIndex mappingsIndex, EntryTree<EntryMapping> jarProposedMappings, EntryTree<EntryMapping> deobfMappings, List<NameProposalService> proposalServices) {
private EntryRemapper(
Enigma enigma, JarIndex jarIndex, JarIndex combinedIndex,
MappingsIndex mappingsIndex,
EntryTree<EntryMapping> jarProposedMappings, EntryTree<EntryMapping> deobfMappings,
List<NameProposalService> proposalServices
) {
this.deobfMappings = deobfMappings;
this.jarProposedMappings = jarProposedMappings;
this.proposedMappings = new HashEntryTree<>(jarProposedMappings);
Expand All @@ -58,16 +64,67 @@ private EntryRemapper(Enigma enigma, JarIndex jarIndex, MappingsIndex mappingsIn
this.jarIndex = jarIndex;
this.mappingsIndex = mappingsIndex;

this.validator = new MappingValidator(this.obfResolver, this.deobfuscator, jarIndex, mappingsIndex);
// use combined index for validator so it can find conflicts with lib method names
final EntryResolver combinedResolver = combinedIndex.getEntryResolver();
this.validator = new MappingValidator(combinedResolver, new MappingTranslator(this.mappings, combinedResolver), combinedIndex, mappingsIndex);
this.proposalServices = proposalServices;
}

public static EntryRemapper mapped(Enigma enigma, JarIndex jarIndex, MappingsIndex mappingsIndex, EntryTree<EntryMapping> proposedMappings, EntryTree<EntryMapping> deobfMappings, List<NameProposalService> proposalServices) {
return new EntryRemapper(enigma, jarIndex, mappingsIndex, proposedMappings, deobfMappings, proposalServices);
public static EntryRemapper mapped(
Enigma project, JarIndex jarIndex, JarIndex combinedIndex,
MappingsIndex mappingsIndex,
EntryTree<EntryMapping> proposedMappings, EntryTree<EntryMapping> deobfMappings,
List<NameProposalService> proposalServices
) {
return new EntryRemapper(
project, jarIndex, combinedIndex,
mappingsIndex,
proposedMappings, deobfMappings,
proposalServices
);
}

public static EntryRemapper empty(Enigma enigma, JarIndex index, List<NameProposalService> proposalServices) {
return new EntryRemapper(enigma, index, MappingsIndex.empty(), new HashEntryTree<>(), new HashEntryTree<>(), proposalServices);
/**
* Creates a remapper with the passed {@code project}'s {@linkplain EnigmaProject#getEnigma() enigma} instance,
* {@linkplain EnigmaProject#getJarIndex() jar index}, {@linkplain EnigmaProject#getCombinedIndex() combined index},
* {@linkplain EnigmaProject#getMappingsIndex() mappings index},
* and its enigma instance's {@linkplain Enigma#getNameProposalServices() name proposal services}.
*/
public static EntryRemapper mapped(
EnigmaProject project, EntryTree<EntryMapping> proposedMappings, EntryTree<EntryMapping> deobfMappings
) {
return mapped(
project.getEnigma(), project.getJarIndex(), project.getCombinedIndex(),
project.getMappingsIndex(),
proposedMappings, deobfMappings,
project.getEnigma().getNameProposalServices()
);
}

public static EntryRemapper empty(
Enigma enigma,
JarIndex jarIndex, JarIndex combinedIndex,
List<NameProposalService> proposalServices
) {
return new EntryRemapper(
enigma, jarIndex, combinedIndex,
MappingsIndex.empty(), new HashEntryTree<>(), new HashEntryTree<>(),
proposalServices
);
}

/**
* Creates an empty remapper with the passed {@code project}'s
* {@linkplain EnigmaProject#getEnigma() enigma} instance,
* {@linkplain EnigmaProject#getJarIndex() jar index}, {@linkplain EnigmaProject#getCombinedIndex() combined index},
* and its enigma instance's {@linkplain Enigma#getNameProposalServices() name proposal services}.
*/
public static EntryRemapper empty(EnigmaProject project) {
return empty(
project.getEnigma(),
project.getJarIndex(), project.getCombinedIndex(),
project.getEnigma().getNameProposalServices()
);
}

public void validatePutMapping(ValidationContext vc, Entry<?> obfuscatedEntry, @NonNull EntryMapping deobfMapping) {
Expand All @@ -82,7 +139,9 @@ private void doPutMapping(ValidationContext vc, Entry<?> obfuscatedEntry, @NonNu
EntryMapping oldMapping = this.getMapping(obfuscatedEntry);
boolean renaming = !Objects.equals(oldMapping.targetName(), deobfMapping.targetName());

Collection<Entry<?>> resolvedEntries = renaming ? this.resolveAllRoots(obfuscatedEntry) : this.obfResolver.resolveEntry(obfuscatedEntry, ResolutionStrategy.RESOLVE_CLOSEST);
Collection<Entry<?>> resolvedEntries = renaming
? this.resolveAllRoots(obfuscatedEntry)
: this.obfResolver.resolveEntry(obfuscatedEntry, ResolutionStrategy.RESOLVE_CLOSEST);

if (renaming && deobfMapping.targetName() != null) {
for (Entry<?> resolvedEntry : resolvedEntries) {
Expand Down
70 changes: 70 additions & 0 deletions enigma/src/test/java/org/quiltmc/enigma/TestMainJarMapped.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package org.quiltmc.enigma;

import org.junit.jupiter.api.Test;
import org.quiltmc.enigma.api.Enigma;
import org.quiltmc.enigma.api.EnigmaProject;
import org.quiltmc.enigma.api.ProgressListener;
import org.quiltmc.enigma.api.class_provider.ClasspathClassProvider;
import org.quiltmc.enigma.api.translation.mapping.EntryMapping;
import org.quiltmc.enigma.api.translation.mapping.serde.MappingFileNameFormat;
import org.quiltmc.enigma.api.translation.mapping.serde.MappingSaveParameters;
import org.quiltmc.enigma.api.translation.representation.entry.LocalVariableEntry;
import org.quiltmc.enigma.util.validation.ValidationContext;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Stream;

import static org.junit.jupiter.api.Assertions.assertEquals;

public class TestMainJarMapped {
private static final Path JAR = TestUtil.obfJar("main_jar_mapped");

public static final String TEST_CLASS_NAME = "a";

private static EnigmaProject openProject() {
try {
return Enigma.create().openJar(JAR, new ClasspathClassProvider(), ProgressListener.createEmpty());
} catch (IOException e) {
throw new RuntimeException(e);
}
}

/**
* Tests that when a parameter of a main jar method that's inherited from a lib class is mapped,
* the main jar's parameter is mapped; no lib mapping should be created.
*/
@Test
void test() throws IOException {
final EnigmaProject project = openProject();

final LocalVariableEntry equalsParam = TestEntryFactory.newParameter(
TestEntryFactory.newMethod(TEST_CLASS_NAME, "equals", "(Ljava/lang/Object;)Z"),
1
);

project.getRemapper().putMapping(new ValidationContext(null), equalsParam, new EntryMapping("object"));

final Path mappingsDir = Files.createTempDirectory("main_jar_mapped");
project.getEnigma()
.getReadWriteService(mappingsDir)
.orElseThrow()
.write(
project.getRemapper().getMappings(),
mappingsDir,
new MappingSaveParameters(MappingFileNameFormat.BY_DEOBF, false, null, null)
);

final List<Path> savedFiles = new LinkedList<>();
try (Stream<Path> paths = Files.walk(mappingsDir)) {
paths.filter(Files::isRegularFile).forEach(savedFiles::add);
}

assertEquals(1, savedFiles.size());

assertEquals(mappingsDir.resolve(TEST_CLASS_NAME + ".mapping"), savedFiles.get(0));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package org.quiltmc.enigma.input.main_jar_mapped;

public class MainJarMapped {
@Override
public boolean equals(Object o) {
return false;
}
}