Skip to content

Commit

Permalink
fallback name proposal and name proposal save bypass (#240)
Browse files Browse the repository at this point in the history
* add methods and start work on tests

* actually use that method oops

* implement bypassValidation()

* implement fallback for stats

* checkstyle tests

* store a full `EntryMapping` in `TranslateResult`

* add highlighting for fallback mappings

* fix crash with trailing commas in profile json

* add test proposer for fallback
- fix highlighting
- only propose names for the first parameter of each method in test:parameters

* orange!

* good looking colors for fallback

* checkstyle

* checkstyle

* rethrow exceptions in tests

* fix dynamic proposal not accounting for unchecked

* fix dynamic proposal putting obf mappings in the wrong tree

* checkstyle
  • Loading branch information
ix0rai authored Dec 17, 2024
1 parent 3a1981d commit dda4efe
Show file tree
Hide file tree
Showing 27 changed files with 668 additions and 108 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,12 @@
import org.quiltmc.enigma.gui.config.Config;
import org.quiltmc.enigma.gui.highlight.BoxHighlightPainter;
import org.quiltmc.enigma.gui.util.ScaleUtil;
import org.quiltmc.enigma.api.source.TokenType;
import org.quiltmc.syntaxpain.JavaSyntaxKit;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.image.BufferedImage;
import java.util.Map;
import javax.swing.JEditorPane;
import javax.swing.JPanel;
import javax.swing.UIManager;
Expand Down Expand Up @@ -79,14 +77,24 @@ private static void setFonts() {
UIManager.put("Button.font", bold);
}

public static Map<TokenType, BoxHighlightPainter> getBoxHighlightPainters() {
return Map.of(
TokenType.OBFUSCATED, BoxHighlightPainter.create(Config.getCurrentSyntaxPaneColors().obfuscated.value(), Config.getCurrentSyntaxPaneColors().obfuscatedOutline.value()),
TokenType.JAR_PROPOSED, BoxHighlightPainter.create(Config.getCurrentSyntaxPaneColors().proposed.value(), Config.getCurrentSyntaxPaneColors().proposedOutline.value()),
TokenType.DYNAMIC_PROPOSED, BoxHighlightPainter.create(Config.getCurrentSyntaxPaneColors().proposed.value(), Config.getCurrentSyntaxPaneColors().proposedOutline.value()),
TokenType.DEOBFUSCATED, BoxHighlightPainter.create(Config.getCurrentSyntaxPaneColors().deobfuscated.value(), Config.getCurrentSyntaxPaneColors().deobfuscatedOutline.value()),
TokenType.DEBUG, BoxHighlightPainter.create(Config.getCurrentSyntaxPaneColors().debugToken.value(), Config.getCurrentSyntaxPaneColors().debugTokenOutline.value())
);
public static BoxHighlightPainter createObfuscatedPainter() {
return BoxHighlightPainter.create(Config.getCurrentSyntaxPaneColors().obfuscated.value(), Config.getCurrentSyntaxPaneColors().obfuscatedOutline.value());
}

public static BoxHighlightPainter createProposedPainter() {
return BoxHighlightPainter.create(Config.getCurrentSyntaxPaneColors().proposed.value(), Config.getCurrentSyntaxPaneColors().proposedOutline.value());
}

public static BoxHighlightPainter createDeobfuscatedPainter() {
return BoxHighlightPainter.create(Config.getCurrentSyntaxPaneColors().deobfuscated.value(), Config.getCurrentSyntaxPaneColors().deobfuscatedOutline.value());
}

public static BoxHighlightPainter createDebugPainter() {
return BoxHighlightPainter.create(Config.getCurrentSyntaxPaneColors().debugToken.value(), Config.getCurrentSyntaxPaneColors().debugTokenOutline.value());
}

public static BoxHighlightPainter createFallbackPainter() {
return BoxHighlightPainter.create(Config.getCurrentSyntaxPaneColors().fallback.value(), Config.getCurrentSyntaxPaneColors().fallbackOutline.value());
}

public static <T> void resetIfAbsent(TrackedValue<T> value) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ public Colors.Builder buildSyntaxPaneColors(Colors.Builder colors) {
.deobfuscated(new SerializableColor(0x4D50FA7B))
.deobfuscatedOutline(new SerializableColor(0x8050FA7B))

.fallback(new SerializableColor(0x4Daa5500))
.fallbackOutline(new SerializableColor(0x80d86f06))

.editorBackground(new SerializableColor(0xFF282A36))
.highlight(new SerializableColor(0xFFFF79C6))
.caret(new SerializableColor(0xFFF8F8F2))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ public static class Colors implements Consumer<Config.SectionBuilder> {
public final TrackedValue<ThemeProperties.SerializableColor> deobfuscated;
public final TrackedValue<ThemeProperties.SerializableColor> deobfuscatedOutline;

public final TrackedValue<ThemeProperties.SerializableColor> fallback;
public final TrackedValue<ThemeProperties.SerializableColor> fallbackOutline;

public final TrackedValue<ThemeProperties.SerializableColor> editorBackground;
public final TrackedValue<ThemeProperties.SerializableColor> highlight;
public final TrackedValue<ThemeProperties.SerializableColor> caret;
Expand Down Expand Up @@ -78,6 +81,9 @@ private Colors(
ThemeProperties.SerializableColor deobfuscated,
ThemeProperties.SerializableColor deobfuscatedOutline,

ThemeProperties.SerializableColor fallback,
ThemeProperties.SerializableColor fallbackOutline,

ThemeProperties.SerializableColor editorBackground,
ThemeProperties.SerializableColor highlight,
ThemeProperties.SerializableColor caret,
Expand Down Expand Up @@ -106,6 +112,9 @@ private Colors(
this.deobfuscated = TrackedValue.create(deobfuscated, "deobfuscated");
this.deobfuscatedOutline = TrackedValue.create(deobfuscatedOutline, "deobfuscated_outline");

this.fallback = TrackedValue.create(fallback, "fallback");
this.fallbackOutline = TrackedValue.create(fallbackOutline, "fallbackOutline");

this.editorBackground = TrackedValue.create(editorBackground, "editor_background");
this.highlight = TrackedValue.create(highlight, "highlight");
this.caret = TrackedValue.create(caret, "caret");
Expand Down Expand Up @@ -142,6 +151,9 @@ public Stream<TrackedValue<ThemeProperties.SerializableColor>> stream() {
this.deobfuscated,
this.deobfuscatedOutline,

this.fallback,
this.fallbackOutline,

this.editorBackground,
this.highlight,
this.caret,
Expand Down Expand Up @@ -177,6 +189,9 @@ public static class Builder {
private ThemeProperties.SerializableColor deobfuscated = new ThemeProperties.SerializableColor(0xFFDCFFDC);
private ThemeProperties.SerializableColor deobfuscatedOutline = new ThemeProperties.SerializableColor(0xFF50A050);

private ThemeProperties.SerializableColor fallback = new ThemeProperties.SerializableColor(0xFFffddbb);
private ThemeProperties.SerializableColor fallbackOutline = new ThemeProperties.SerializableColor(0xFFd86f06);

private ThemeProperties.SerializableColor editorBackground = new ThemeProperties.SerializableColor(0xFFFFFFFF);
private ThemeProperties.SerializableColor highlight = new ThemeProperties.SerializableColor(0xFF3333EE);
private ThemeProperties.SerializableColor caret = new ThemeProperties.SerializableColor(0xFF000000);
Expand Down Expand Up @@ -207,6 +222,9 @@ public Colors build() {
this.deobfuscated,
this.deobfuscatedOutline,

this.fallback,
this.fallbackOutline,

this.editorBackground,
this.highlight,
this.caret,
Expand Down Expand Up @@ -270,6 +288,16 @@ public Builder deobfuscatedOutline(ThemeProperties.SerializableColor deobfuscate
return this;
}

public Builder fallback(ThemeProperties.SerializableColor fallback) {
this.fallback = fallback;
return this;
}

public Builder fallbackOutline(ThemeProperties.SerializableColor fallbackOutline) {
this.fallbackOutline = fallbackOutline;
return this;
}

public Builder editorBackground(ThemeProperties.SerializableColor editorBackground) {
this.editorBackground = editorBackground;
return this;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.quiltmc.enigma.gui.element;

import org.quiltmc.enigma.api.source.TokenType;
import org.quiltmc.enigma.gui.ClassSelector;
import org.quiltmc.enigma.gui.Gui;
import org.quiltmc.enigma.gui.docker.ClassesDocker;
Expand Down Expand Up @@ -126,7 +127,7 @@ public void show(ClassSelector selector, int x, int y) {
// update toggle mapping text to match
this.toggleMapping.setEnabled(selected != null);
if (selected != null) {
if (this.gui.getController().getProject().getRemapper().extendedDeobfuscate(selected).isDeobfuscated()) {
if (this.gui.getController().getProject().getRemapper().extendedDeobfuscate(selected).getType() == TokenType.DEOBFUSCATED) {
this.toggleMapping.setText(I18n.translate("popup_menu.reset_obfuscated"));
} else {
this.toggleMapping.setText(I18n.translate("popup_menu.mark_deobfuscated"));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.quiltmc.enigma.gui.element;

import org.quiltmc.enigma.api.analysis.EntryReference;
import org.quiltmc.enigma.api.source.TokenType;
import org.quiltmc.enigma.gui.EditableType;
import org.quiltmc.enigma.gui.Gui;
import org.quiltmc.enigma.gui.GuiController;
Expand Down Expand Up @@ -171,7 +172,7 @@ public void updateUiState() {
this.openNextItem.setEnabled(controller.hasNextReference());
this.toggleMappingItem.setEnabled(isRenamable && (type != null && this.gui.isEditable(type)));

if (referenceEntry != null && this.gui.getController().getProject().getRemapper().extendedDeobfuscate(referenceEntry).isDeobfuscated()) {
if (referenceEntry != null && this.gui.getController().getProject().getRemapper().extendedDeobfuscate(referenceEntry).getType() == TokenType.DEOBFUSCATED) {
this.toggleMappingItem.setText(I18n.translate("popup_menu.reset_obfuscated"));
} else {
this.toggleMappingItem.setText(I18n.translate("popup_menu.mark_deobfuscated"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import org.quiltmc.enigma.api.class_handle.ClassHandle;
import org.quiltmc.enigma.api.class_handle.ClassHandleError;
import org.quiltmc.enigma.api.event.ClassHandleListener;
import org.quiltmc.enigma.api.source.TokenStore;
import org.quiltmc.enigma.gui.BrowserCaret;
import org.quiltmc.enigma.gui.EditableType;
import org.quiltmc.enigma.gui.Gui;
Expand Down Expand Up @@ -96,7 +97,11 @@ public class EditorPanel {
private boolean shouldNavigateOnClick;

private int fontSize = 12;
private final Map<TokenType, BoxHighlightPainter> boxHighlightPainters;
private final BoxHighlightPainter obfuscatedPainter;
private final BoxHighlightPainter proposedPainter;
private final BoxHighlightPainter deobfuscatedPainter;
private final BoxHighlightPainter debugPainter;
public final BoxHighlightPainter fallbackPainter;

private final List<EditorActionListener> listeners = new ArrayList<>();

Expand Down Expand Up @@ -132,7 +137,11 @@ public EditorPanel(Gui gui, NavigatorPanel navigator) {
this.errorTextArea.setEditable(false);
this.errorTextArea.setFont(ScaleUtil.getFont(Font.MONOSPACED, Font.PLAIN, 10));

this.boxHighlightPainters = ThemeUtil.getBoxHighlightPainters();
this.obfuscatedPainter = ThemeUtil.createObfuscatedPainter();
this.proposedPainter = ThemeUtil.createProposedPainter();
this.debugPainter = ThemeUtil.createDebugPainter();
this.fallbackPainter = ThemeUtil.createFallbackPainter();
this.deobfuscatedPainter = ThemeUtil.createDeobfuscatedPainter();

this.editor.addMouseListener(new MouseAdapter() {
@Override
Expand Down Expand Up @@ -464,7 +473,7 @@ public void setSource(DecompiledClassSource source) {
this.editor.getHighlighter().removeAllHighlights();
this.editor.setText(source.toString());

this.setHighlightedTokens(source.getHighlightedTokens());
this.setHighlightedTokens(source.getTokenStore(), source.getHighlightedTokens());
if (this.source != null) {
this.editor.setCaretPosition(newCaretPos);

Expand All @@ -484,32 +493,30 @@ public void setSource(DecompiledClassSource source) {
}
}

public void setHighlightedTokens(Map<TokenType, ? extends Collection<Token>> tokens) {
public void setHighlightedTokens(TokenStore tokenStore, Map<TokenType, ? extends Collection<Token>> tokens) {
// remove any old highlighters
this.editor.getHighlighter().removeAllHighlights();

if (this.boxHighlightPainters != null) {
BoxHighlightPainter proposedPainter = this.boxHighlightPainters.get(TokenType.JAR_PROPOSED);

for (TokenType type : tokens.keySet()) {
BoxHighlightPainter painter = this.boxHighlightPainters.get(type);

if (painter != null) {
for (Token token : tokens.get(type)) {
EntryReference<Entry<?>, Entry<?>> reference = this.getReference(token);
BoxHighlightPainter tokenPainter;

if (reference != null) {
EditableType t = EditableType.fromEntry(reference.entry);
boolean editable = t == null || this.gui.isEditable(t);
tokenPainter = editable ? painter : proposedPainter;
} else {
tokenPainter = painter;
}

this.addHighlightedToken(token, tokenPainter);
}
for (TokenType type : tokens.keySet()) {
BoxHighlightPainter typePainter = switch (type) {
case OBFUSCATED -> this.obfuscatedPainter;
case DEOBFUSCATED -> this.deobfuscatedPainter;
case DEBUG -> this.debugPainter;
case JAR_PROPOSED, DYNAMIC_PROPOSED -> this.proposedPainter;
};

for (Token token : tokens.get(type)) {
BoxHighlightPainter tokenPainter = typePainter;
EntryReference<Entry<?>, Entry<?>> reference = this.getReference(token);

if (reference != null) {
EditableType t = EditableType.fromEntry(reference.entry);
boolean editable = t == null || this.gui.isEditable(t);
boolean fallback = tokenStore.isFallback(token);
tokenPainter = editable ? (fallback ? this.fallbackPainter : typePainter) : this.proposedPainter;
}

this.addHighlightedToken(token, tokenPainter);
}
}

Expand Down
20 changes: 18 additions & 2 deletions enigma/src/main/java/org/quiltmc/enigma/api/Enigma.java
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ public EnigmaProject openJar(Path path, ClassProvider libraryClassProvider, Prog

if (proposed != null) {
for (var entry : proposed.entrySet()) {
if (entry.getValue() != null && entry.getValue().tokenType() != TokenType.JAR_PROPOSED) {
if (!service.bypassValidation() && entry.getValue() != null && entry.getValue().tokenType() != TokenType.JAR_PROPOSED) {
throw new RuntimeException("Token type of mapping " + entry.getValue() + " for entry " + entry.getKey() + " was " + entry.getValue().tokenType() + ", but should be " + TokenType.JAR_PROPOSED + "!");
}

Expand Down Expand Up @@ -197,6 +197,22 @@ public Optional<ReadWriteService> getReadWriteService(Path path) {
return this.parseFileType(path).flatMap(this::getReadWriteService);
}

/**
* Searches for and returns a service with a matching id to the provided {@code id}.
* @param type the type of the searched service
* @param id the id of the service
* @return the optional service
*/
public <T extends EnigmaService> Optional<T> getService(EnigmaServiceType<T> type, String id) {
for (T service : this.services.get(type)) {
if (service.getId().equals(id)) {
return Optional.of(service);
}
}

return Optional.empty();
}

public static void validatePluginId(String id) {
if (id != null && !id.matches("([a-z0-9_]+):([a-z0-9_]+((/[a-z0-9_]+)+)?)")) {
throw new IllegalArgumentException("Invalid plugin id: \"" + id + "\"\n" + "Refer to Javadoc on EnigmaService#getId for how to properly form a service ID.");
Expand Down Expand Up @@ -310,7 +326,7 @@ public <T extends EnigmaService> void registerService(EnigmaServiceType<T> servi

for (EnigmaProfile.Service serviceProfile : serviceProfiles) {
T service = factory.create(this.getServiceContext(serviceProfile));
if (serviceProfile.matches(service.getId())) {
if (serviceProfile != null && serviceProfile.matches(service.getId())) {
this.putService(serviceType, service);
break;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,22 @@ public interface NameProposalService extends EnigmaService {
@Nullable
Map<Entry<?>, EntryMapping> getDynamicProposedNames(EntryRemapper remapper, @Nullable Entry<?> obfEntry, @Nullable EntryMapping oldMapping, @Nullable EntryMapping newMapping);

default boolean isFallback() {
return false;
}

/**
* Disables validation of proposed mappings from this service.
* This allows you to return any kind of mapping you want from {@link #getDynamicProposedNames(EntryRemapper, Entry, EntryMapping, EntryMapping)}
* and {@link #getProposedNames(JarIndex)}, but should be used sparingly as it will allow creating mappings that can't be linked back to this proposer.
* Do not use this unless you're sure there's no other way to accomplish what you're looking to do!
*
* @return whether validation should be bypassed
*/
default boolean bypassValidation() {
return false;
}

/**
* Creates a proposed mapping, with no javadoc and using {@link #getId()} as the source plugin ID.
* @param name the name
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import org.quiltmc.enigma.api.analysis.EntryReference;
import org.quiltmc.enigma.api.translation.TranslateResult;
import org.quiltmc.enigma.api.translation.Translator;
import org.quiltmc.enigma.api.translation.mapping.EntryMapping;
import org.quiltmc.enigma.api.translation.representation.TypeDescriptor;
import org.quiltmc.enigma.api.translation.representation.entry.ClassEntry;
import org.quiltmc.enigma.api.translation.representation.entry.Entry;
Expand Down Expand Up @@ -57,14 +58,14 @@ private String remapToken(TokenStore target, EnigmaProject project, Token token,
TranslateResult<Entry<?>> translatedEntry = translator.extendedTranslate(entry);

if (project.isRenamable(reference)) {
if (!translatedEntry.isObfuscated()) {
target.add(translatedEntry.getType(), movedToken);
if (translatedEntry != null && !translatedEntry.isObfuscated()) {
target.add(project, translatedEntry.getMapping(), movedToken);
return translatedEntry.getValue().getSourceRemapName();
} else {
target.add(TokenType.OBFUSCATED, movedToken);
target.add(project, EntryMapping.OBFUSCATED, movedToken);
}
} else if (DEBUG_TOKEN_HIGHLIGHTS) {
target.add(TokenType.DEBUG, movedToken);
target.add(project, new EntryMapping(null, null, TokenType.DEBUG, null), movedToken);
}

return this.generateDefaultName(translatedEntry.getValue());
Expand Down
Loading

0 comments on commit dda4efe

Please sign in to comment.