Skip to content

Commit

Permalink
reload ancestors of a class when its stats are changed - fixes #230
Browse files Browse the repository at this point in the history
  • Loading branch information
ix0rai committed Oct 10, 2024
1 parent 57c74af commit fa70bd1
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 5 deletions.
17 changes: 14 additions & 3 deletions enigma-swing/src/main/java/org/quiltmc/enigma/gui/Gui.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import org.quiltmc.enigma.api.Enigma;
import org.quiltmc.enigma.api.EnigmaProfile;
import org.quiltmc.enigma.api.analysis.EntryReference;
import org.quiltmc.enigma.api.analysis.index.jar.InheritanceIndex;
import org.quiltmc.enigma.api.source.TokenType;
import org.quiltmc.enigma.api.translation.mapping.EntryMapping;
import org.quiltmc.enigma.api.translation.mapping.EntryRemapper;
Expand Down Expand Up @@ -586,18 +587,28 @@ public void moveClassTree(ClassEntry classEntry, boolean updateSwingState, boole
allClassesSelector.restoreExpansionState(expansionState);
deobfuscatedClassSelector.restoreExpansionState(deobfuscatedPanelExpansionState);
obfuscatedClassSelector.restoreExpansionState(obfuscatedPanelExpansionState);
this.reloadStats(classEntry);
this.reloadStats(classEntry, false);
}
}

/**
* Reloads stats for the provided class in all selectors.
* @param classEntry the class to reload
* @param propagate whether to also reload ancestors of the class
*/
public void reloadStats(ClassEntry classEntry) {
public void reloadStats(ClassEntry classEntry, boolean propagate) {
List<ClassEntry> toUpdate = new ArrayList<>();
toUpdate.add(classEntry);
if (propagate) {
Collection<ClassEntry> parents = this.controller.getProject().getJarIndex().getIndex(InheritanceIndex.class).getAncestors(classEntry);
toUpdate.addAll(parents);
}

for (Docker value : this.dockerManager.getDockers()) {
if (value instanceof ClassesDocker docker) {
docker.getClassSelector().reloadStats(classEntry);
for (ClassEntry entry : toUpdate) {
docker.getClassSelector().reloadStats(entry);
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -576,7 +576,9 @@ private void applyChange0(ValidationContext vc, EntryChange<?> change, boolean u
boolean isNewOb = mapping.targetName() == null;
this.gui.moveClassTree(target.getContainingClass(), updateSwingState, isOldOb, isNewOb);
} else if (updateSwingState) {
this.gui.reloadStats(change.getTarget().getTopLevelClass());
// update stat icons for classes that could have had their mappings changed by this update
boolean propagate = target instanceof FieldEntry || target instanceof MethodEntry || target instanceof LocalVariableEntry;
this.gui.reloadStats(change.getTarget().getTopLevelClass(), propagate);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package org.quiltmc.enigma.stats;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.quiltmc.enigma.TestEntryFactory;
import org.quiltmc.enigma.TestUtil;
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.JarClassProvider;
import org.quiltmc.enigma.api.stats.StatType;
import org.quiltmc.enigma.api.stats.StatsGenerator;
import org.quiltmc.enigma.api.stats.StatsResult;
import org.quiltmc.enigma.api.translation.mapping.EntryMapping;
import org.quiltmc.enigma.api.translation.representation.entry.ClassEntry;
import org.quiltmc.enigma.api.translation.representation.entry.MethodEntry;

import java.io.IOException;
import java.nio.file.Path;
import java.util.Set;

public class TestStatGenerationInheritance {
private static final Path JAR = TestUtil.obfJar("interfaces");
private static EnigmaProject project;

@BeforeEach
void openProject() {
try {
Enigma enigma = Enigma.create();
project = enigma.openJar(JAR, new JarClassProvider(JAR), ProgressListener.createEmpty());
} catch (IOException e) {
throw new RuntimeException(e);
}
}

@Test
void testInterfacePropagation() {
// https://github.com/QuiltMC/enigma/issues/230 - verifying backend bit
ClassEntry interfaceEntry = TestEntryFactory.newClass("b");
ClassEntry inheritorEntry = TestEntryFactory.newClass("a");

StatsResult interfaceResult = new StatsGenerator(project).generate(Set.of(StatType.METHODS), interfaceEntry, false);
Assertions.assertEquals(2, interfaceResult.getMappable());

// the inheritor does not own the method; it won't count towards its stats
StatsResult inheritorResult = new StatsGenerator(project).generate(Set.of(StatType.METHODS), inheritorEntry, false);
Assertions.assertEquals(0, inheritorResult.getMappable());

MethodEntry inheritedMethod = TestEntryFactory.newMethod(inheritorEntry, "a", "(D)D");
project.getRemapper().putMapping(TestUtil.newVC(), inheritedMethod, new EntryMapping("mapped"));

StatsResult interfaceResult2 = new StatsGenerator(project).generate(Set.of(StatType.METHODS), interfaceEntry, false);
Assertions.assertEquals(1, interfaceResult2.getMapped());
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.quiltmc.enigma;
package org.quiltmc.enigma.stats;

import org.quiltmc.enigma.TestUtil;
import org.quiltmc.enigma.api.Enigma;
import org.quiltmc.enigma.api.EnigmaProject;
import org.quiltmc.enigma.api.ProgressListener;
Expand Down

0 comments on commit fa70bd1

Please sign in to comment.